add scroll mouse support x, y

This commit is contained in:
vcaesar 2018-02-25 15:22:52 +08:00
parent 4544fabb91
commit 0a93336c11
3 changed files with 198 additions and 118 deletions

View File

@ -64,7 +64,7 @@ int drag_mouse(size_t x, size_t y){
return 0; return 0;
} }
bool move_mouse_smooth(size_t x, size_t y, double lowSpeed, bool move_mouse_smooth(size_t x, size_t y, double lowSpeed,
double highSpeed, int msDelay){ double highSpeed, int msDelay){
MMPoint point; MMPoint point;
point = MMPointMake(x, y); point = MMPointMake(x, y);
@ -110,6 +110,7 @@ int mouse_toggle(char* d, MMMouseButton button){
toggleMouse(down, button); toggleMouse(down, button);
microsleep(mouseDelay); microsleep(mouseDelay);
return 0; return 0;
} }
@ -120,6 +121,13 @@ int set_mouse_delay(size_t val){
return 0; return 0;
} }
int scroll(int x, int y, int msDelay){
scrollMouseXY(x, y);
microsleep(msDelay);
return 0;
}
int scroll_mouse(size_t scrollMagnitude, char *s){ int scroll_mouse(size_t scrollMagnitude, char *s){
// int scrollMagnitude = 20; // int scrollMagnitude = 20;

View File

@ -66,8 +66,7 @@
* @param event The mouse move event (by ref). * @param event The mouse move event (by ref).
* @param point The new mouse x and y. * @param point The new mouse x and y.
*/ */
void calculateDeltas(CGEventRef *event, MMPoint point) void calculateDeltas(CGEventRef *event, MMPoint point){
{
/** /**
* The next few lines are a workaround for games not detecting mouse moves. * The next few lines are a workaround for games not detecting mouse moves.
* See this issue for more information: * See this issue for more information:
@ -92,81 +91,78 @@ void calculateDeltas(CGEventRef *event, MMPoint point)
* Move the mouse to a specific point. * Move the mouse to a specific point.
* @param point The coordinates to move the mouse to (x, y). * @param point The coordinates to move the mouse to (x, y).
*/ */
void moveMouse(MMPoint point) void moveMouse(MMPoint point){
{ #if defined(IS_MACOSX)
#if defined(IS_MACOSX) CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved,
CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, CGPointFromMMPoint(point),
CGPointFromMMPoint(point), kCGMouseButtonLeft);
kCGMouseButtonLeft);
calculateDeltas(&move, point); calculateDeltas(&move, point);
CGEventPost(kCGSessionEventTap, move); CGEventPost(kCGSessionEventTap, move);
CFRelease(move); CFRelease(move);
#elif defined(USE_X11) #elif defined(USE_X11)
Display *display = XGetMainDisplay(); Display *display = XGetMainDisplay();
XWarpPointer(display, None, DefaultRootWindow(display), XWarpPointer(display, None, DefaultRootWindow(display),
0, 0, 0, 0, point.x, point.y); 0, 0, 0, 0, point.x, point.y);
XFlush(display); XFlush(display);
#elif defined(IS_WINDOWS) #elif defined(IS_WINDOWS)
//Mouse motion is now done using SendInput with MOUSEINPUT. We use Absolute mouse positioning //Mouse motion is now done using SendInput with MOUSEINPUT. We use Absolute mouse positioning
#define MOUSE_COORD_TO_ABS(coord, width_or_height) (((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1)) #define MOUSE_COORD_TO_ABS(coord, width_or_height) (((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1))
point.x = MOUSE_COORD_TO_ABS(point.x, GetSystemMetrics(SM_CXSCREEN)); point.x = MOUSE_COORD_TO_ABS(point.x, GetSystemMetrics(SM_CXSCREEN));
point.y = MOUSE_COORD_TO_ABS(point.y, GetSystemMetrics(SM_CYSCREEN)); point.y = MOUSE_COORD_TO_ABS(point.y, GetSystemMetrics(SM_CYSCREEN));
INPUT mouseInput; INPUT mouseInput;
mouseInput.type = INPUT_MOUSE; mouseInput.type = INPUT_MOUSE;
mouseInput.mi.dx = point.x; mouseInput.mi.dx = point.x;
mouseInput.mi.dy = point.y; mouseInput.mi.dy = point.y;
mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
mouseInput.mi.time = 0; //System will provide the timestamp mouseInput.mi.time = 0; //System will provide the timestamp
mouseInput.mi.dwExtraInfo = 0; mouseInput.mi.dwExtraInfo = 0;
mouseInput.mi.mouseData = 0; mouseInput.mi.mouseData = 0;
SendInput(1, &mouseInput, sizeof(mouseInput)); SendInput(1, &mouseInput, sizeof(mouseInput));
#endif #endif
} }
void dragMouse(MMPoint point, const MMMouseButton button) void dragMouse(MMPoint point, const MMMouseButton button){
{ #if defined(IS_MACOSX)
#if defined(IS_MACOSX) const CGEventType dragType = MMMouseDragToCGEventType(button);
const CGEventType dragType = MMMouseDragToCGEventType(button); CGEventRef drag = CGEventCreateMouseEvent(NULL, dragType,
CGEventRef drag = CGEventCreateMouseEvent(NULL, dragType, CGPointFromMMPoint(point),
CGPointFromMMPoint(point), (CGMouseButton)button);
(CGMouseButton)button); calculateDeltas(&drag, point);
calculateDeltas(&drag, point);
CGEventPost(kCGSessionEventTap, drag); CGEventPost(kCGSessionEventTap, drag);
CFRelease(drag); CFRelease(drag);
#else #else
moveMouse(point); moveMouse(point);
#endif #endif
} }
MMPoint getMousePos() MMPoint getMousePos(){
{ #if defined(IS_MACOSX)
#if defined(IS_MACOSX) CGEventRef event = CGEventCreate(NULL);
CGEventRef event = CGEventCreate(NULL); CGPoint point = CGEventGetLocation(event);
CGPoint point = CGEventGetLocation(event); CFRelease(event);
CFRelease(event);
return MMPointFromCGPoint(point); return MMPointFromCGPoint(point);
#elif defined(USE_X11) #elif defined(USE_X11)
int x, y; /* This is all we care about. Seriously. */ int x, y; /* This is all we care about. Seriously. */
Window garb1, garb2; /* Why you can't specify NULL as a parameter */ Window garb1, garb2; /* Why you can't specify NULL as a parameter */
int garb_x, garb_y; /* is beyond me. */ int garb_x, garb_y; /* is beyond me. */
unsigned int more_garbage; unsigned int more_garbage;
Display *display = XGetMainDisplay(); Display *display = XGetMainDisplay();
XQueryPointer(display, XDefaultRootWindow(display), &garb1, &garb2, XQueryPointer(display, XDefaultRootWindow(display), &garb1, &garb2,
&x, &y, &garb_x, &garb_y, &more_garbage); &x, &y, &garb_x, &garb_y, &more_garbage);
return MMPointMake(x, y); return MMPointMake(x, y);
#elif defined(IS_WINDOWS) #elif defined(IS_WINDOWS)
POINT point; POINT point;
GetCursorPos(&point); GetCursorPos(&point);
return MMPointFromPOINT(point); return MMPointFromPOINT(point);
#endif #endif
} }
/** /**
@ -174,28 +170,26 @@ MMPoint getMousePos()
* @param down True for down, false for up. * @param down True for down, false for up.
* @param button The button to press down or release. * @param button The button to press down or release.
*/ */
void toggleMouse(bool down, MMMouseButton button) void toggleMouse(bool down, MMMouseButton button){
{ #if defined(IS_MACOSX)
#if defined(IS_MACOSX) const CGPoint currentPos = CGPointFromMMPoint(getMousePos());
const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); const CGEventType mouseType = MMMouseToCGEventType(down, button);
const CGEventType mouseType = MMMouseToCGEventType(down, button); CGEventRef event = CGEventCreateMouseEvent(NULL,
CGEventRef event = CGEventCreateMouseEvent(NULL, mouseType,
mouseType, currentPos,
currentPos, (CGMouseButton)button);
(CGMouseButton)button); CGEventPost(kCGSessionEventTap, event);
CGEventPost(kCGSessionEventTap, event); CFRelease(event);
CFRelease(event); #elif defined(USE_X11)
#elif defined(USE_X11) Display *display = XGetMainDisplay();
Display *display = XGetMainDisplay(); XTestFakeButtonEvent(display, button, down ? True : False, CurrentTime);
XTestFakeButtonEvent(display, button, down ? True : False, CurrentTime); XFlush(display);
XFlush(display); #elif defined(IS_WINDOWS)
#elif defined(IS_WINDOWS) mouse_event(MMMouseToMEventF(down, button), 0, 0, 0, 0);
mouse_event(MMMouseToMEventF(down, button), 0, 0, 0, 0); #endif
#endif
} }
void clickMouse(MMMouseButton button) void clickMouse(MMMouseButton button){
{
toggleMouse(true, button); toggleMouse(true, button);
toggleMouse(false, button); toggleMouse(false, button);
} }
@ -204,36 +198,34 @@ void clickMouse(MMMouseButton button)
* Special function for sending double clicks, needed for Mac OS X. * Special function for sending double clicks, needed for Mac OS X.
* @param button Button to click. * @param button Button to click.
*/ */
void doubleClick(MMMouseButton button) void doubleClick(MMMouseButton button){
{ #if defined(IS_MACOSX)
#if defined(IS_MACOSX) /* Double click for Mac. */
const CGPoint currentPos = CGPointFromMMPoint(getMousePos());
const CGEventType mouseTypeDown = MMMouseToCGEventType(true, button);
const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button);
/* Double click for Mac. */ CGEventRef event = CGEventCreateMouseEvent(NULL, mouseTypeDown, currentPos, kCGMouseButtonLeft);
const CGPoint currentPos = CGPointFromMMPoint(getMousePos());
const CGEventType mouseTypeDown = MMMouseToCGEventType(true, button);
const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button);
CGEventRef event = CGEventCreateMouseEvent(NULL, mouseTypeDown, currentPos, kCGMouseButtonLeft); /* Set event to double click. */
CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2);
/* Set event to double click. */ CGEventPost(kCGHIDEventTap, event);
CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2);
CGEventPost(kCGHIDEventTap, event); CGEventSetType(event, mouseTypeUP);
CGEventPost(kCGHIDEventTap, event);
CGEventSetType(event, mouseTypeUP); CFRelease(event);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event); #else
#else /* Double click for everything else. */
clickMouse(button);
microsleep(200);
clickMouse(button);
/* Double click for everything else. */ #endif
clickMouse(button);
microsleep(200);
clickMouse(button);
#endif
} }
/** /**
@ -241,8 +233,7 @@ void doubleClick(MMMouseButton button)
* This uses the magnitude to scroll the required amount in the direction. * This uses the magnitude to scroll the required amount in the direction.
* TODO Requires further fine tuning based on the requirements. * TODO Requires further fine tuning based on the requirements.
*/ */
void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection) void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){
{
#if defined(IS_WINDOWS) #if defined(IS_WINDOWS)
// Fix for #97 https://github.com/go-vgo/robotgo/issues/97, // Fix for #97 https://github.com/go-vgo/robotgo/issues/97,
// C89 needs variables declared on top of functions (mouseScrollInput) // C89 needs variables declared on top of functions (mouseScrollInput)
@ -252,8 +243,7 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection)
/* Direction should only be considered based on the scrollDirection. This /* Direction should only be considered based on the scrollDirection. This
* Should not interfere. */ * Should not interfere. */
int cleanScrollMagnitude = abs(scrollMagnitude); int cleanScrollMagnitude = abs(scrollMagnitude);
if (!(scrollDirection == DIRECTION_UP || scrollDirection == DIRECTION_DOWN)) if (!(scrollDirection == DIRECTION_UP || scrollDirection == DIRECTION_DOWN)){
{
return; return;
} }
@ -303,6 +293,76 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection)
#endif #endif
} }
void scrollMouseXY(int x, int y){
#if defined(IS_WINDOWS)
// Fix for #97,
// C89 needs variables declared on top of functions (mouseScrollInput)
INPUT mouseScrollInputH;
INPUT mouseScrollInputV;
#endif
/* Direction should only be considered based on the scrollDirection. This
* Should not interfere. */
/* Set up the OS specific solution */
#if defined(__APPLE__)
CGEventRef event;
event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, y, x);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
#elif defined(USE_X11)
int ydir = 4; /* Button 4 is up, 5 is down. */
int xdir = 6;
Display *display = XGetMainDisplay();
if (y < 0){
ydir = 5;
}
if (x < 0){
xdir = 7;
}
int xi;
int yi;
for (xi = 0; xi < abs(x); xi++) {
XTestFakeButtonEvent(display, xdir, 1, CurrentTime);
XTestFakeButtonEvent(display, xdir, 0, CurrentTime);
}
for (yi = 0; yi < abs(y); yi++) {
XTestFakeButtonEvent(display, ydir, 1, CurrentTime);
XTestFakeButtonEvent(display, ydir, 0, CurrentTime);
}
XFlush(display);
#elif defined(IS_WINDOWS)
mouseScrollInputH.type = INPUT_MOUSE;
mouseScrollInputH.mi.dx = 0;
mouseScrollInputH.mi.dy = 0;
mouseScrollInputH.mi.dwFlags = MOUSEEVENTF_WHEEL;
mouseScrollInputH.mi.time = 0;
mouseScrollInputH.mi.dwExtraInfo = 0;
mouseScrollInputH.mi.mouseData = WHEEL_DELTA * x;
mouseScrollInputV.type = INPUT_MOUSE;
mouseScrollInputV.mi.dx = 0;
mouseScrollInputV.mi.dy = 0;
mouseScrollInputV.mi.dwFlags = MOUSEEVENTF_HWHEEL;
mouseScrollInputV.mi.time = 0;
mouseScrollInputV.mi.dwExtraInfo = 0;
mouseScrollInputV.mi.mouseData = WHEEL_DELTA * y;
SendInput(1, &mouseScrollInputH, sizeof(mouseScrollInputH));
SendInput(1, &mouseScrollInputV, sizeof(mouseScrollInputV));
#endif
}
/* /*
* A crude, fast hypot() approximation to get around the fact that hypot() is * A crude, fast hypot() approximation to get around the fact that hypot() is
* not a standard ANSI C function. * not a standard ANSI C function.
@ -313,8 +373,7 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection)
* http://stackoverflow.com/questions/3506404/fast-hypotenuse-algorithm-for-embedded-processor#3507882 * http://stackoverflow.com/questions/3506404/fast-hypotenuse-algorithm-for-embedded-processor#3507882
* *
*/ */
static double crude_hypot(double x, double y) static double crude_hypot(double x, double y){
{
double big = fabs(x); /* max(|x|, |y|) */ double big = fabs(x); /* max(|x|, |y|) */
double small = fabs(y); /* min(|x|, |y|) */ double small = fabs(y); /* min(|x|, |y|) */
@ -327,8 +386,7 @@ static double crude_hypot(double x, double y)
return ((M_SQRT2 - 1.0) * small) + big; return ((M_SQRT2 - 1.0) * small) + big;
} }
bool smoothlyMoveMouse(MMPoint endPoint, double lowSpeed, double highSpeed) bool smoothlyMoveMouse(MMPoint endPoint, double lowSpeed, double highSpeed){
{
MMPoint pos = getMousePos(); MMPoint pos = getMousePos();
MMSize screenSize = getMainDisplaySize(); MMSize screenSize = getMainDisplaySize();
double velo_x = 0.0, velo_y = 0.0; double velo_x = 0.0, velo_y = 0.0;

View File

@ -543,9 +543,23 @@ func SetMouseDelay(x int) {
// ScrollMouse scroll the mouse // ScrollMouse scroll the mouse
func ScrollMouse(x int, y string) { func ScrollMouse(x int, y string) {
cx := C.size_t(x) cx := C.size_t(x)
z := C.CString(y) cy := C.CString(y)
C.scroll_mouse(cx, z) C.scroll_mouse(cx, cy)
defer C.free(unsafe.Pointer(z))
defer C.free(unsafe.Pointer(cy))
}
func Scroll(x, y int, args ...int) {
var msDelay = 10
if len(args) > 0 {
msDelay = args[0]
}
cx := C.int(x)
cy := C.int(y)
cz:=C.int(msDelay)
C.scroll(cx, cy, cz)
} }
/* /*