Skip to content

Commit 7b1c5fb

Browse files
committed
Fix Multiple monitor support for mouseSmoothMove. NOTE: not the most 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
1 parent 99021d8 commit 7b1c5fb

File tree

6 files changed

+62
-29
lines changed

6 files changed

+62
-29
lines changed

src/mouse.c

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ void updateScreenMetrics()
108108
* Move the mouse to a specific point.
109109
* @param point The coordinates to move the mouse to (x, y).
110110
*/
111-
void moveMouse(MMSignedPoint point)
111+
void moveMouse(MMSignedPoint point, bool sm)
112112
{
113113
#if defined(IS_MACOSX)
114114
CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved,
@@ -128,13 +128,20 @@ void moveMouse(MMSignedPoint point)
128128

129129
if(vscreenWidth<0 || vscreenHeight<0)
130130
updateScreenMetrics();
131-
132-
//Mouse motion is now done using SendInput with MOUSEINPUT. We use Absolute mouse positioning
133-
#define MOUSE_COORD_TO_ABS(coord, width_or_height) ((65536 * (coord) / width_or_height) + ((coord) < 0 ? -1 : 1))
134-
135-
size_t x = MOUSE_COORD_TO_ABS(point.x-vscreenMinX, vscreenWidth);
136-
size_t y = MOUSE_COORD_TO_ABS(point.y-vscreenMinY, vscreenHeight);
137-
131+
int32_t x = 0;
132+
int32_t y = 0;
133+
if (!sm)
134+
{
135+
//Mouse motion is now done using SendInput with MOUSEINPUT. We use Absolute mouse positioning
136+
#define MOUSE_COORD_TO_ABS(coord, width_or_height) ((65536 * (coord) / width_or_height) + ((coord) < 0 ? -1 : 1))
137+
138+
x = MOUSE_COORD_TO_ABS(point.x - vscreenMinX, vscreenWidth);
139+
y = MOUSE_COORD_TO_ABS(point.y - vscreenMinY, vscreenHeight);
140+
}
141+
else {
142+
x = point.x;
143+
y = point.y;
144+
}
138145
INPUT mouseInput = {0};
139146
mouseInput.type = INPUT_MOUSE;
140147
mouseInput.mi.dx = x;
@@ -158,11 +165,11 @@ void dragMouse(MMSignedPoint point, const MMMouseButton button)
158165
CGEventPost(kCGSessionEventTap, drag);
159166
CFRelease(drag);
160167
#else
161-
moveMouse(point);
168+
moveMouse(point,false);
162169
#endif
163170
}
164171

165-
MMPoint getMousePos()
172+
MMSignedPoint getMousePos()
166173
{
167174
#if defined(IS_MACOSX)
168175
CGEventRef event = CGEventCreate(NULL);
@@ -184,8 +191,13 @@ MMPoint getMousePos()
184191
#elif defined(IS_WINDOWS)
185192
POINT point;
186193
GetCursorPos(&point);
194+
if (vscreenWidth < 0 || vscreenHeight < 0)
195+
updateScreenMetrics();
196+
#define MOUSE_COORD_TO_ABS(coord, width_or_height) ((65536 * (coord) / width_or_height) + ((coord) < 0 ? -1 : 1))
187197

188-
return MMPointFromPOINT(point);
198+
int32_t x = MOUSE_COORD_TO_ABS(point.x - vscreenMinX, vscreenWidth);
199+
int32_t y = MOUSE_COORD_TO_ABS(point.y - vscreenMinY, vscreenHeight);
200+
return MMSignedPointFromPOINT(point);
189201
#endif
190202
}
191203

@@ -370,15 +382,18 @@ static double crude_hypot(double x, double y)
370382
return ((M_SQRT2 - 1.0) * small) + big;
371383
}
372384

373-
bool smoothlyMoveMouse(MMPoint endPoint,double speed)
385+
bool smoothlyMoveMouse(MMPoint endPoint, double speed)
374386
{
375-
MMPoint pos = getMousePos();
376-
MMSize screenSize = getMainDisplaySize();
387+
MMSignedPoint pos = getMousePos();
388+
MMSignedSize screenSize = getMainDisplaySize();
377389
double velo_x = 0.0, velo_y = 0.0;
378390
double distance;
379-
391+
int32_t x, y = 0;
392+
if (vscreenWidth < 0 || vscreenHeight < 0)
393+
updateScreenMetrics();
394+
double bdist = (distance = crude_hypot((double)pos.x - endPoint.x,(double)pos.y - endPoint.y));
380395
while ((distance = crude_hypot((double)pos.x - endPoint.x,
381-
(double)pos.y - endPoint.y)) > 1.0) {
396+
(double)pos.y - endPoint.y)) > 1.0) {
382397
double gravity = DEADBEEF_UNIFORM(5.0, 500.0);
383398
double veloDistance;
384399
velo_x += (gravity * ((double)endPoint.x - pos.x)) / distance;
@@ -397,11 +412,14 @@ bool smoothlyMoveMouse(MMPoint endPoint,double speed)
397412
if (pos.x >= screenSize.width || pos.y >= screenSize.height) {
398413
return false;
399414
}
415+
#define MOUSE_COORD_TO_ABS(coord, width_or_height) ((65536 * (coord) / width_or_height) + ((coord) < 0 ? -1 : 1))
400416

401-
moveMouse(MMSignedPointMake((int32_t)pos.x, (int32_t)pos.y));
417+
x = MOUSE_COORD_TO_ABS(pos.x - vscreenMinX, vscreenWidth);
418+
y = MOUSE_COORD_TO_ABS(pos.y - vscreenMinY, vscreenHeight);
419+
moveMouse(MMSignedPointMake(x,y),true);
402420

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

407425
return true;

src/mouse.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void updateScreenMetrics();
6666
/* Immediately moves the mouse to the given point on-screen.
6767
* It is up to the caller to ensure that this point is within the
6868
* screen boundaries. */
69-
void moveMouse(MMSignedPoint point);
69+
void moveMouse(MMSignedPoint point, bool sm);
7070

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

8484
/* Returns the coordinates of the mouse on the current screen. */
85-
MMPoint getMousePos(void);
85+
MMSignedPoint getMousePos(void);
8686

8787
/* Holds down or releases the mouse with the given button in the current
8888
* position. */

src/robotjs.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ NAN_METHOD(moveMouse)
107107

108108
MMSignedPoint point;
109109
point = MMSignedPointMake(x, y);
110-
moveMouse(point);
110+
moveMouse(point,false);
111111
microsleep(mouseDelay);
112112

113113
info.GetReturnValue().Set(Nan::New(1));
@@ -140,7 +140,7 @@ NAN_METHOD(moveMouseSmooth)
140140

141141
NAN_METHOD(getMousePos)
142142
{
143-
MMPoint pos = getMousePos();
143+
MMSignedPoint pos = getMousePos();
144144

145145
//Return object with .x and .y.
146146
Local<Object> obj = Nan::New<Object>();
@@ -689,7 +689,7 @@ NAN_METHOD(getPixelColor)
689689
NAN_METHOD(getScreenSize)
690690
{
691691
//Get display size.
692-
MMSize displaySize = getMainDisplaySize();
692+
MMSignedSize displaySize = getMainDisplaySize();
693693

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

748748
//Get screen size.
749-
MMSize displaySize = getMainDisplaySize();
749+
MMSignedSize displaySize = getMainDisplaySize();
750750
w = displaySize.width;
751751
h = displaySize.height;
752752
}

src/screen.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include "xdisplay.h"
99
#endif
1010

11-
MMSize getMainDisplaySize(void)
11+
MMSignedSize getMainDisplaySize(void)
1212
{
1313
#if defined(IS_MACOSX)
1414
CGDirectDisplayID displayID = CGMainDisplayID();
@@ -21,13 +21,13 @@ MMSize getMainDisplaySize(void)
2121
return MMSizeMake((size_t)DisplayWidth(display, screen),
2222
(size_t)DisplayHeight(display, screen));
2323
#elif defined(IS_WINDOWS)
24-
return MMSizeMake((size_t)GetSystemMetrics(SM_CXSCREEN),
25-
(size_t)GetSystemMetrics(SM_CYSCREEN));
24+
return MMSignedSizeMake((size_t)GetSystemMetrics(SM_CXVIRTUALSCREEN),
25+
(size_t)GetSystemMetrics(SM_CYVIRTUALSCREEN));
2626
#endif
2727
}
2828

2929
bool pointVisibleOnMainDisplay(MMPoint point)
3030
{
31-
MMSize displaySize = getMainDisplaySize();
31+
MMSignedSize displaySize = getMainDisplaySize();
3232
return point.x < displaySize.width && point.y < displaySize.height;
3333
}

src/screen.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extern "C"
1616
#endif
1717

1818
/* Returns the size of the main display. */
19-
MMSize getMainDisplaySize(void);
19+
MMSignedSize getMainDisplaySize(void);
2020

2121
/* Convenience function that returns whether the given point is in the bounds
2222
* of the main screen. */

src/types.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ struct _MMSize {
3131

3232
typedef struct _MMSize MMSize;
3333

34+
struct _MMSignedSize {
35+
int32_t width;
36+
int32_t height;
37+
};
38+
39+
typedef struct _MMSignedSize MMSignedSize;
40+
3441
struct _MMRect {
3542
MMPoint origin;
3643
MMSize size;
@@ -61,6 +68,13 @@ H_INLINE MMSize MMSizeMake(size_t width, size_t height)
6168
size.height = height;
6269
return size;
6370
}
71+
H_INLINE MMSignedSize MMSignedSizeMake(int32_t width, int32_t height)
72+
{
73+
MMSignedSize size;
74+
size.width = width;
75+
size.height = height;
76+
return size;
77+
}
6478

6579
H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height)
6680
{
@@ -83,6 +97,7 @@ H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height)
8397
#elif defined(IS_WINDOWS)
8498

8599
#define MMPointFromPOINT(p) MMPointMake((size_t)p.x, (size_t)p.y)
100+
#define MMSignedPointFromPOINT(p) MMSignedPointMake((int32_t)p.x, (int32_t)p.y)
86101

87102
#endif
88103

0 commit comments

Comments
 (0)