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

org.sikuli.script.Mouse Maven / Gradle / Ivy

/*
 * Copyright 2010-2014, Sikuli.org, sikulix.com
 * Released under the MIT License.
 *
 * modified RaiMan
 */
package org.sikuli.script;

import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import org.sikuli.basics.Debug;
import org.sikuli.basics.Settings;

/**
 * Main pupose is to coordinate the mouse usage among threads 
* At any one time, the mouse has one owner (usually a Region object)
* who exclusively uses the mouse, all others wait for the mouse to be free again
* if more than one possible owner is waiting, the next owner is uncertain
* It is detected, when the mouse is moved external from the workflow, which can be used for * appropriate actions (e.g. pause a script)
* the mouse can be blocked for a longer time, so only this owner can use the mouse (like some * transactional processing)
* Currently deadlocks and infinite waits are not detected, but should not happen ;-)
* Contained are methods to use the mouse (click, move, button down/up) as is */ public class Mouse { private static String me = "Mouse: "; private static final int lvl = 3; private static void log(int level, String message, Object... args) { Debug.logx(level, me + message, args); } private static Mouse mouse = null; private Device device = null; protected Location mousePos; protected boolean clickDouble; protected int buttons; protected int beforeWait; protected int innerWait; protected int afterWait; public static final int LEFT = InputEvent.BUTTON1_MASK; public static final int MIDDLE = InputEvent.BUTTON2_MASK; public static final int RIGHT = InputEvent.BUTTON3_MASK; public static final int WHEEL_UP = -1; public static int WHEEL_DOWN = 1; public static final int WHEEL_STEP_DELAY = 50; private Mouse() { } public static void init() { if (mouse == null) { mouse = new Mouse(); mouse.device = new Device(mouse); mouse.device.isMouse = true; move(at()); mouse.device.lastPos = null; log(3, "init"); } } private static Mouse get() { if (mouse == null) { init(); } return mouse; } protected static boolean use() { return get().device.use(null); } protected static boolean use(Object owner) { return get().device.use(owner); } protected static boolean keep(Object owner) { return get().device.keep(owner); } protected static boolean let() { return get().device.let(null); } protected static boolean let(Object owner) { return get().get().device.let(owner); } public static Location at() { return get().device.getLocation(); } public static void reset() { if (mouse == null) { return; } get().device.unblock(get().device.owner); mouse.get().device.let(get().device.owner); get().device.let(get().device.owner); up(); get().device.mouseMovedResponse = get().device.MouseMovedIgnore; get().device.mouseMovedCallback = null; get().device.callback = null; get().device.lastPos = null; } /** * current setting what to do if mouse is moved outside Sikuli's mouse protection * * @return current setting see {@link #setMouseMovedAction(int)} */ public static int getMouseMovedResponse() { return get().device.mouseMovedResponse; } /** * what to do if mouse is moved outside Sikuli's mouse protection
* - Mouse.MouseMovedIgnore (0) ignore it (default)
* - Mouse.MouseMovedShow (1) show and ignore it
* - Mouse.MouseMovedPause (2) show it and pause until user says continue
* (2 not implemented yet - 1 is used) * * @param movedAction value */ public static void setMouseMovedAction(int movedAction) { if (movedAction > -1 && movedAction < 3) { get().device.mouseMovedResponse = movedAction; get().device.mouseMovedCallback = null; log(lvl, "setMouseMovedAction: %d", get().device.mouseMovedResponse); } } /** * what to do if mouse is moved outside Sikuli's mouse protection
* only 3 is honored:
* in case of event the user provided callBack.happened is called * * @param callBack ObserverCallBack */ public static void setMouseMovedCallback(Object callBack) { if (callBack != null) { get().device.mouseMovedResponse = 3; get().device.mouseMovedCallback = new ObserverCallBack(callBack, ObserveEvent.Type.GENERIC); } } /** * * @param state */ public static void setMouseMovedHighlight(boolean state) { get().device.MouseMovedHighlight = state; } /** * check if mouse was moved since last mouse action * * @return true/false */ public static boolean hasMoved() { Location pos = get().device.getLocation(); if (get().device.lastPos.x != pos.x || get().device.lastPos.y != pos.y) { return true; } return false; } /** * to click (left, right, middle - single or double) at the given location using the given button * only useable for local screens * * timing parameters:
* - one value
* < 0 wait before mouse down
* > 0 wait after mouse up
* - 2 or 3 values 1st wait before mouse down
* 2nd wait after mouse up
* 3rd inner wait (milli secs, cut to 1000): pause between mouse down and up (Settings.ClickDelay) * * wait before and after: > 59 taken as milli secs - < are seconds * * @param loc where to click * @param action L,R,M left, right, middle - D means double click * @param args timing parameters * @return the location */ public static Location click(Location loc, String action, Integer... args) { if (get().device.isSuspended() || loc.isOtherScreen()) { return null; } getArgsClick(loc, action, args); get().device.use(); Device.delay(mouse.beforeWait); Settings.ClickDelay = mouse.innerWait / 1000; click(loc, mouse.buttons, 0, ((Mouse) get()).clickDouble, null); Device.delay(mouse.afterWait); get().device.let(); return loc; } private static void getArgsClick(Location loc, String action, Integer... args) { mouse.mousePos = loc; mouse.clickDouble = false; action = action.toUpperCase(); if (action.contains("D")) { mouse.clickDouble = true; } mouse.buttons = 0; if (action.contains("L")) { mouse.buttons += LEFT; } if (action.contains("M")) { mouse.buttons += MIDDLE; } if (action.contains("R")) { mouse.buttons += RIGHT; } if (mouse.buttons == 0) { mouse.buttons = LEFT; } mouse.beforeWait = 0; mouse.innerWait = 0; mouse.afterWait = 0; if (args.length > 0) { if (args.length == 1) { if (args[0] < 0) { mouse.beforeWait = -args[0]; } else { mouse.afterWait = args[0]; } } mouse.beforeWait = args[0]; if (args.length > 1) { mouse.afterWait = args[1]; if (args.length > 2) { mouse.innerWait = args[2]; } } } } protected static int click(Location loc, int buttons, Integer modifiers, boolean dblClick, Region region) { if (modifiers == null) { modifiers = 0; } Debug profiler = Debug.startTimer("Mouse.click"); boolean shouldMove = true; if (loc == null) { shouldMove = false; loc = at(); } IRobot r = null; r = Screen.getMouseRobot(); if (r == null) { profiler.end(); return 0; } get().device.use(region); profiler.lap("after use"); Debug.action(getClickMsg(loc, buttons, modifiers, dblClick)); if (shouldMove) { r.smoothMove(loc); profiler.lap("after move"); } r.clickStarts(); r.pressModifiers(modifiers); int pause = Settings.ClickDelay > 1 ? 1 : (int) (Settings.ClickDelay * 1000); Settings.ClickDelay = 0.0; if (dblClick) { r.mouseDown(buttons); r.mouseUp(buttons); r.mouseDown(buttons); r.mouseUp(buttons); } else { r.mouseDown(buttons); r.delay(pause); r.mouseUp(buttons); } r.releaseModifiers(modifiers); r.clickEnds(); r.waitForIdle(); profiler.lap("before let"); get().device.let(region); profiler.end(); return 1; } private static String getClickMsg(Location loc, int buttons, int modifiers, boolean dblClick) { String msg = ""; if (modifiers != 0) { msg += KeyEvent.getKeyModifiersText(modifiers) + "+"; } if (buttons == InputEvent.BUTTON1_MASK && !dblClick) { msg += "CLICK"; } if (buttons == InputEvent.BUTTON1_MASK && dblClick) { msg += "DOUBLE CLICK"; } if (buttons == InputEvent.BUTTON3_MASK) { msg += "RIGHT CLICK"; } else if (buttons == InputEvent.BUTTON2_MASK) { msg += "MID CLICK"; } msg += " on " + loc; return msg; } /** * move the mouse to the given location (local and remote) * * @param loc Location * @return 1 for success, 0 otherwise */ public static int move(Location loc) { return move(loc, null); } /** * move the mouse from the current position to the offset position given by the parameters * @param xoff horizontal offset (< 0 left, > 0 right) * @param yoff vertical offset (< 0 up, > 0 down) * @return 1 for success, 0 otherwise */ public static int move(int xoff, int yoff) { return move(at().offset(xoff, yoff)); } protected static int move(Location loc, Region region) { if (get().device.isSuspended()) { return 0; } if (loc != null) { IRobot r = null; r = Screen.getMouseRobot(); if (r == null) { return 0; } if (!r.isRemote()) { get().device.use(region); } r.smoothMove(loc); r.waitForIdle(); if (!r.isRemote()) { get().device.let(region); } return 1; } return 0; } /** * press and hold the given buttons {@link Button} * * @param buttons value */ public static void down(int buttons) { down(buttons, null); } protected static void down(int buttons, Region region) { if (get().device.isSuspended()) { return; } get().device.use(region); Screen.getMouseRobot().mouseDown(buttons); } /** * release all buttons * */ public static void up() { up(0, null); } /** * release the given buttons {@link Button} * * @param buttons (0 releases all buttons) */ public static void up(int buttons) { up(buttons, null); } protected static void up(int buttons, Region region) { if (get().device.isSuspended()) { return; } Screen.getMouseRobot().mouseUp(buttons); if (region != null) { get().device.let(region); } } /** * move mouse using mouse wheel in the given direction the given steps
* the result is system dependent * * @param direction {@link Button} * @param steps value */ public static void wheel(int direction, int steps) { wheel(direction, steps, null); } protected static void wheel(int direction, int steps, Region region) { wheel(direction,steps,region, WHEEL_STEP_DELAY); } protected static void wheel(int direction, int steps, Region region, int stepDelay) { if (get().device.isSuspended()) { return; } IRobot r = Screen.getMouseRobot(); get().device.use(region); Debug.log(3, "Region: wheel: %s steps: %d", (direction == WHEEL_UP ? "WHEEL_UP" : "WHEEL_DOWN"), steps); for (int i = 0; i < steps; i++) { r.mouseWheel(direction); r.delay(stepDelay); } get().device.let(region); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy