-
-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
400 additions
and
345 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#include "../mouse.h" | ||
#include "../microsleep.h" | ||
|
||
#include <math.h> /* For floor() */ | ||
|
||
#include <X11/Xlib.h> | ||
#include <X11/extensions/XTest.h> | ||
#include <stdlib.h> | ||
#include "../xdisplay.h" | ||
|
||
#if !defined(M_SQRT2) | ||
#define M_SQRT2 1.4142135623730950488016887 /* Fix for MSVC. */ | ||
#endif | ||
|
||
/** | ||
* Move the mouse to a specific point. | ||
* @param point The coordinates to move the mouse to (x, y). | ||
*/ | ||
void moveMouse(MMPoint point) | ||
{ | ||
Display *display = XGetMainDisplay(); | ||
XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, point.x, point.y); | ||
XSync(display, false); | ||
} | ||
|
||
void dragMouse(MMPoint point, const MMMouseButton button) | ||
{ | ||
moveMouse(point); | ||
} | ||
|
||
MMPoint getMousePos() | ||
{ | ||
int x, y; /* This is all we care about. Seriously. */ | ||
Window garb1, garb2; /* Why you can't specify NULL as a parameter */ | ||
int garb_x, garb_y; /* is beyond me. */ | ||
unsigned int more_garbage; | ||
|
||
Display *display = XGetMainDisplay(); | ||
XQueryPointer(display, XDefaultRootWindow(display), &garb1, &garb2, &x, &y, &garb_x, &garb_y, &more_garbage); | ||
|
||
return MMPointMake(x, y); | ||
} | ||
|
||
/** | ||
* Press down a button, or release it. | ||
* @param down True for down, false for up. | ||
* @param button The button to press down or release. | ||
*/ | ||
void toggleMouse(bool down, MMMouseButton button) | ||
{ | ||
Display *display = XGetMainDisplay(); | ||
XTestFakeButtonEvent(display, button, down ? True : False, CurrentTime); | ||
XSync(display, false); | ||
} | ||
|
||
void clickMouse(MMMouseButton button) | ||
{ | ||
toggleMouse(true, button); | ||
toggleMouse(false, button); | ||
} | ||
|
||
/** | ||
* Special function for sending double clicks, needed for Mac OS X. | ||
* @param button Button to click. | ||
*/ | ||
void doubleClick(MMMouseButton button) | ||
{ | ||
clickMouse(button); | ||
microsleep(200); | ||
clickMouse(button); | ||
} | ||
|
||
void scrollMouse(int x, int y) | ||
{ | ||
/* | ||
X11 Mouse Button Numbering | ||
1 = left button | ||
2 = middle button (pressing the scroll wheel) | ||
3 = right button | ||
4 = turn scroll wheel up | ||
5 = turn scroll wheel down | ||
6 = push scroll wheel left | ||
7 = push scroll wheel right | ||
8 = 4th button (aka browser backward button) | ||
9 = 5th button (aka browser forward button) | ||
*/ | ||
int ydir = 4; // Button 4 is up, 5 is down. | ||
int xdir = 6; // Button 6 is left, 7 is right. | ||
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); | ||
} | ||
|
||
XSync(display, false); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
#include "../mouse.h" | ||
#include "../microsleep.h" | ||
|
||
#include <math.h> /* For floor() */ | ||
#include <ApplicationServices/ApplicationServices.h> | ||
|
||
#if !defined(M_SQRT2) | ||
#define M_SQRT2 1.4142135623730950488016887 /* Fix for MSVC. */ | ||
#endif | ||
|
||
#define MMMouseToCGEventType(down, button) \ | ||
(down ? MMMouseDownToCGEventType(button) : MMMouseUpToCGEventType(button)) | ||
|
||
#define MMMouseDownToCGEventType(button) \ | ||
((button) == (LEFT_BUTTON) ? kCGEventLeftMouseDown \ | ||
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseDown \ | ||
: kCGEventOtherMouseDown)) | ||
|
||
#define MMMouseUpToCGEventType(button) \ | ||
((button) == LEFT_BUTTON ? kCGEventLeftMouseUp \ | ||
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseUp \ | ||
: kCGEventOtherMouseUp)) | ||
|
||
#define MMMouseDragToCGEventType(button) \ | ||
((button) == LEFT_BUTTON ? kCGEventLeftMouseDragged \ | ||
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseDragged \ | ||
: kCGEventOtherMouseDragged)) | ||
|
||
/** | ||
* Calculate the delta for a mouse move and add them to the event. | ||
* @param event The mouse move event (by ref). | ||
* @param point The new mouse x and y. | ||
*/ | ||
void calculateDeltas(CGEventRef *event, MMPoint point) | ||
{ | ||
/** | ||
* The next few lines are a workaround for games not detecting mouse moves. | ||
* See this issue for more information: | ||
* https://github.com/octalmage/robotjs/issues/159 | ||
*/ | ||
CGEventRef get = CGEventCreate(NULL); | ||
CGPoint mouse = CGEventGetLocation(get); | ||
|
||
// Calculate the deltas. | ||
int64_t deltaX = point.x - mouse.x; | ||
int64_t deltaY = point.y - mouse.y; | ||
|
||
CGEventSetIntegerValueField(*event, kCGMouseEventDeltaX, deltaX); | ||
CGEventSetIntegerValueField(*event, kCGMouseEventDeltaY, deltaY); | ||
|
||
CFRelease(get); | ||
} | ||
|
||
/** | ||
* Move the mouse to a specific point. | ||
* @param point The coordinates to move the mouse to (x, y). | ||
*/ | ||
void moveMouse(MMPoint point) | ||
{ | ||
CGPoint position = CGPointMake(point.x, point.y); | ||
// Create an HID hardware event source | ||
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); | ||
|
||
CGEventRef evt = NULL; | ||
if (CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonLeft)) | ||
{ | ||
// Create a left button drag | ||
evt = CGEventCreateMouseEvent(src, kCGEventLeftMouseDragged, position, kCGMouseButtonLeft); | ||
} | ||
else | ||
{ | ||
if (CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonRight)) | ||
{ | ||
// Create a right button drag | ||
evt = CGEventCreateMouseEvent(src, kCGEventRightMouseDragged, position, kCGMouseButtonLeft); | ||
} | ||
else | ||
{ | ||
// Create a mouse move event | ||
evt = CGEventCreateMouseEvent(src, kCGEventMouseMoved, position, kCGMouseButtonLeft); | ||
} | ||
} | ||
|
||
// Post mouse event and release | ||
CGEventPost(kCGHIDEventTap, evt); | ||
if (evt != NULL) | ||
{ | ||
CFRelease(evt); | ||
} | ||
CFRelease(src); | ||
} | ||
|
||
void dragMouse(MMPoint point, const MMMouseButton button) | ||
{ | ||
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); | ||
const CGEventType dragType = MMMouseDragToCGEventType(button); | ||
CGEventRef drag = CGEventCreateMouseEvent(src, dragType, CGPointFromMMPoint(point), (CGMouseButton)button); | ||
calculateDeltas(&drag, point); | ||
|
||
CGEventPost(kCGHIDEventTap, drag); | ||
CFRelease(drag); | ||
CFRelease(src); | ||
} | ||
|
||
MMPoint getMousePos() | ||
{ | ||
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); | ||
CGEventRef event = CGEventCreate(src); | ||
CGPoint point = CGEventGetLocation(event); | ||
CFRelease(event); | ||
CFRelease(src); | ||
|
||
return MMPointFromCGPoint(point); | ||
} | ||
|
||
/** | ||
* Press down a button, or release it. | ||
* @param down True for down, false for up. | ||
* @param button The button to press down or release. | ||
*/ | ||
void toggleMouse(bool down, MMMouseButton button) | ||
{ | ||
const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); | ||
const CGEventType mouseType = MMMouseToCGEventType(down, button); | ||
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); | ||
CGEventRef event = CGEventCreateMouseEvent(src, mouseType, currentPos, (CGMouseButton)button); | ||
CGEventPost(kCGHIDEventTap, event); | ||
CFRelease(event); | ||
CFRelease(src); | ||
} | ||
|
||
void clickMouse(MMMouseButton button) | ||
{ | ||
toggleMouse(true, button); | ||
toggleMouse(false, button); | ||
} | ||
|
||
/** | ||
* Special function for sending double clicks, needed for Mac OS X. | ||
* @param button Button to click. | ||
*/ | ||
void doubleClick(MMMouseButton button) | ||
{ | ||
/* Double click for Mac. */ | ||
const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); | ||
const CGEventType mouseTypeDown = MMMouseToCGEventType(true, button); | ||
const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button); | ||
|
||
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); | ||
CGEventRef event = CGEventCreateMouseEvent(src, mouseTypeDown, currentPos, kCGMouseButtonLeft); | ||
|
||
/* Set event to double click. */ | ||
CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2); | ||
|
||
CGEventPost(kCGHIDEventTap, event); | ||
|
||
CGEventSetType(event, mouseTypeUP); | ||
CGEventPost(kCGHIDEventTap, event); | ||
|
||
CFRelease(event); | ||
CFRelease(src); | ||
} | ||
|
||
void scrollMouse(int x, int y) | ||
{ | ||
/* | ||
* Direction should only be considered based on the scrollDirection. | ||
* This should not interfere. | ||
* Set up the OS specific solution | ||
*/ | ||
|
||
CGEventRef event; | ||
|
||
event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, y, x); | ||
CGEventPost(kCGHIDEventTap, event); | ||
|
||
CFRelease(event); | ||
} |
Oops, something went wrong.