Skip to content

Commit

Permalink
Fix Multiple monitor support for mouseSmoothMove. NOTE: not the most …
Browse files Browse the repository at this point in the history
…elegant solution and there a few small issues with mouse accelleration due to crude maths. however this will properly get the virtual screen size and map the coordinates calculated in moveMouseSmoothly then pass them to moveMouse pre calculated, with a flag to skip this step in mouseMove. TODO: merge these two functions and call an overload from node to streamline things a bit more
  • Loading branch information
fjlj committed Dec 21, 2019
1 parent 99021d8 commit 7b1c5fb
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 29 deletions.
54 changes: 36 additions & 18 deletions src/mouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void updateScreenMetrics()
* Move the mouse to a specific point.
* @param point The coordinates to move the mouse to (x, y).
*/
void moveMouse(MMSignedPoint point)
void moveMouse(MMSignedPoint point, bool sm)
{
#if defined(IS_MACOSX)
CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved,
Expand All @@ -128,13 +128,20 @@ void moveMouse(MMSignedPoint point)

if(vscreenWidth<0 || vscreenHeight<0)
updateScreenMetrics();

//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))

size_t x = MOUSE_COORD_TO_ABS(point.x-vscreenMinX, vscreenWidth);
size_t y = MOUSE_COORD_TO_ABS(point.y-vscreenMinY, vscreenHeight);

int32_t x = 0;
int32_t y = 0;
if (!sm)
{
//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))

x = MOUSE_COORD_TO_ABS(point.x - vscreenMinX, vscreenWidth);
y = MOUSE_COORD_TO_ABS(point.y - vscreenMinY, vscreenHeight);
}
else {
x = point.x;
y = point.y;
}
INPUT mouseInput = {0};
mouseInput.type = INPUT_MOUSE;
mouseInput.mi.dx = x;
Expand All @@ -158,11 +165,11 @@ void dragMouse(MMSignedPoint point, const MMMouseButton button)
CGEventPost(kCGSessionEventTap, drag);
CFRelease(drag);
#else
moveMouse(point);
moveMouse(point,false);
#endif
}

MMPoint getMousePos()
MMSignedPoint getMousePos()
{
#if defined(IS_MACOSX)
CGEventRef event = CGEventCreate(NULL);
Expand All @@ -184,8 +191,13 @@ MMPoint getMousePos()
#elif defined(IS_WINDOWS)
POINT point;
GetCursorPos(&point);
if (vscreenWidth < 0 || vscreenHeight < 0)
updateScreenMetrics();
#define MOUSE_COORD_TO_ABS(coord, width_or_height) ((65536 * (coord) / width_or_height) + ((coord) < 0 ? -1 : 1))

return MMPointFromPOINT(point);
int32_t x = MOUSE_COORD_TO_ABS(point.x - vscreenMinX, vscreenWidth);
int32_t y = MOUSE_COORD_TO_ABS(point.y - vscreenMinY, vscreenHeight);
return MMSignedPointFromPOINT(point);
#endif
}

Expand Down Expand Up @@ -370,15 +382,18 @@ static double crude_hypot(double x, double y)
return ((M_SQRT2 - 1.0) * small) + big;
}

bool smoothlyMoveMouse(MMPoint endPoint,double speed)
bool smoothlyMoveMouse(MMPoint endPoint, double speed)
{
MMPoint pos = getMousePos();
MMSize screenSize = getMainDisplaySize();
MMSignedPoint pos = getMousePos();
MMSignedSize screenSize = getMainDisplaySize();
double velo_x = 0.0, velo_y = 0.0;
double distance;

int32_t x, y = 0;
if (vscreenWidth < 0 || vscreenHeight < 0)
updateScreenMetrics();
double bdist = (distance = crude_hypot((double)pos.x - endPoint.x,(double)pos.y - endPoint.y));
while ((distance = crude_hypot((double)pos.x - endPoint.x,
(double)pos.y - endPoint.y)) > 1.0) {
(double)pos.y - endPoint.y)) > 1.0) {
double gravity = DEADBEEF_UNIFORM(5.0, 500.0);
double veloDistance;
velo_x += (gravity * ((double)endPoint.x - pos.x)) / distance;
Expand All @@ -397,11 +412,14 @@ bool smoothlyMoveMouse(MMPoint endPoint,double speed)
if (pos.x >= screenSize.width || pos.y >= screenSize.height) {
return false;
}
#define MOUSE_COORD_TO_ABS(coord, width_or_height) ((65536 * (coord) / width_or_height) + ((coord) < 0 ? -1 : 1))

moveMouse(MMSignedPointMake((int32_t)pos.x, (int32_t)pos.y));
x = MOUSE_COORD_TO_ABS(pos.x - vscreenMinX, vscreenWidth);
y = MOUSE_COORD_TO_ABS(pos.y - vscreenMinY, vscreenHeight);
moveMouse(MMSignedPointMake(x,y),true);

/* Wait 1 - (speed) milliseconds. */
microsleep(DEADBEEF_UNIFORM(0.7, speed));
microsleep(DEADBEEF_UNIFORM((min(0.7,speed) + (1-(distance / ((bdist + 0.0001) * 2)))), (max(0.7, speed) - (distance / ((bdist + 0.0001) * 1.5)))));
}

return true;
Expand Down
4 changes: 2 additions & 2 deletions src/mouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void updateScreenMetrics();
/* Immediately moves the mouse to the given point on-screen.
* It is up to the caller to ensure that this point is within the
* screen boundaries. */
void moveMouse(MMSignedPoint point);
void moveMouse(MMSignedPoint point, bool sm);

/* Like moveMouse, moves the mouse to the given point on-screen, but marks
* the event as the mouse being dragged on platforms where it is supported.
Expand All @@ -82,7 +82,7 @@ void dragMouse(MMSignedPoint point, const MMMouseButton button);
bool smoothlyMoveMouse(MMPoint point,double speed);

/* Returns the coordinates of the mouse on the current screen. */
MMPoint getMousePos(void);
MMSignedPoint getMousePos(void);

/* Holds down or releases the mouse with the given button in the current
* position. */
Expand Down
8 changes: 4 additions & 4 deletions src/robotjs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ NAN_METHOD(moveMouse)

MMSignedPoint point;
point = MMSignedPointMake(x, y);
moveMouse(point);
moveMouse(point,false);
microsleep(mouseDelay);

info.GetReturnValue().Set(Nan::New(1));
Expand Down Expand Up @@ -140,7 +140,7 @@ NAN_METHOD(moveMouseSmooth)

NAN_METHOD(getMousePos)
{
MMPoint pos = getMousePos();
MMSignedPoint pos = getMousePos();

//Return object with .x and .y.
Local<Object> obj = Nan::New<Object>();
Expand Down Expand Up @@ -689,7 +689,7 @@ NAN_METHOD(getPixelColor)
NAN_METHOD(getScreenSize)
{
//Get display size.
MMSize displaySize = getMainDisplaySize();
MMSignedSize displaySize = getMainDisplaySize();

//Create our return object.
Local<Object> obj = Nan::New<Object>();
Expand Down Expand Up @@ -746,7 +746,7 @@ NAN_METHOD(captureScreen)
y = 0;

//Get screen size.
MMSize displaySize = getMainDisplaySize();
MMSignedSize displaySize = getMainDisplaySize();
w = displaySize.width;
h = displaySize.height;
}
Expand Down
8 changes: 4 additions & 4 deletions src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "xdisplay.h"
#endif

MMSize getMainDisplaySize(void)
MMSignedSize getMainDisplaySize(void)
{
#if defined(IS_MACOSX)
CGDirectDisplayID displayID = CGMainDisplayID();
Expand All @@ -21,13 +21,13 @@ MMSize getMainDisplaySize(void)
return MMSizeMake((size_t)DisplayWidth(display, screen),
(size_t)DisplayHeight(display, screen));
#elif defined(IS_WINDOWS)
return MMSizeMake((size_t)GetSystemMetrics(SM_CXSCREEN),
(size_t)GetSystemMetrics(SM_CYSCREEN));
return MMSignedSizeMake((size_t)GetSystemMetrics(SM_CXVIRTUALSCREEN),
(size_t)GetSystemMetrics(SM_CYVIRTUALSCREEN));
#endif
}

bool pointVisibleOnMainDisplay(MMPoint point)
{
MMSize displaySize = getMainDisplaySize();
MMSignedSize displaySize = getMainDisplaySize();
return point.x < displaySize.width && point.y < displaySize.height;
}
2 changes: 1 addition & 1 deletion src/screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ extern "C"
#endif

/* Returns the size of the main display. */
MMSize getMainDisplaySize(void);
MMSignedSize getMainDisplaySize(void);

/* Convenience function that returns whether the given point is in the bounds
* of the main screen. */
Expand Down
15 changes: 15 additions & 0 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ struct _MMSize {

typedef struct _MMSize MMSize;

struct _MMSignedSize {
int32_t width;
int32_t height;
};

typedef struct _MMSignedSize MMSignedSize;

struct _MMRect {
MMPoint origin;
MMSize size;
Expand Down Expand Up @@ -61,6 +68,13 @@ H_INLINE MMSize MMSizeMake(size_t width, size_t height)
size.height = height;
return size;
}
H_INLINE MMSignedSize MMSignedSizeMake(int32_t width, int32_t height)
{
MMSignedSize size;
size.width = width;
size.height = height;
return size;
}

H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height)
{
Expand All @@ -83,6 +97,7 @@ H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height)
#elif defined(IS_WINDOWS)

#define MMPointFromPOINT(p) MMPointMake((size_t)p.x, (size_t)p.y)
#define MMSignedPointFromPOINT(p) MMSignedPointMake((int32_t)p.x, (int32_t)p.y)

#endif

Expand Down

0 comments on commit 7b1c5fb

Please sign in to comment.