From 7b1c5fb6c10faf5a3f6721e53c09dc8e86e6a97f Mon Sep 17 00:00:00 2001 From: fjlj Date: Sat, 21 Dec 2019 03:22:08 -0800 Subject: [PATCH 01/18] 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 --- src/mouse.c | 54 +++++++++++++++++++++++++++++++++----------------- src/mouse.h | 4 ++-- src/robotjs.cc | 8 ++++---- src/screen.c | 8 ++++---- src/screen.h | 2 +- src/types.h | 15 ++++++++++++++ 6 files changed, 62 insertions(+), 29 deletions(-) diff --git a/src/mouse.c b/src/mouse.c index e61e8b7c..1c4641bd 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -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, @@ -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; @@ -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); @@ -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 } @@ -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; @@ -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; diff --git a/src/mouse.h b/src/mouse.h index 764f876c..4b3c2565 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -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. @@ -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. */ diff --git a/src/robotjs.cc b/src/robotjs.cc index 8aadd5d1..1596fee7 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -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)); @@ -140,7 +140,7 @@ NAN_METHOD(moveMouseSmooth) NAN_METHOD(getMousePos) { - MMPoint pos = getMousePos(); + MMSignedPoint pos = getMousePos(); //Return object with .x and .y. Local obj = Nan::New(); @@ -689,7 +689,7 @@ NAN_METHOD(getPixelColor) NAN_METHOD(getScreenSize) { //Get display size. - MMSize displaySize = getMainDisplaySize(); + MMSignedSize displaySize = getMainDisplaySize(); //Create our return object. Local obj = Nan::New(); @@ -746,7 +746,7 @@ NAN_METHOD(captureScreen) y = 0; //Get screen size. - MMSize displaySize = getMainDisplaySize(); + MMSignedSize displaySize = getMainDisplaySize(); w = displaySize.width; h = displaySize.height; } diff --git a/src/screen.c b/src/screen.c index e43b6fda..7ffe5cb6 100644 --- a/src/screen.c +++ b/src/screen.c @@ -8,7 +8,7 @@ #include "xdisplay.h" #endif -MMSize getMainDisplaySize(void) +MMSignedSize getMainDisplaySize(void) { #if defined(IS_MACOSX) CGDirectDisplayID displayID = CGMainDisplayID(); @@ -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; } diff --git a/src/screen.h b/src/screen.h index 68860ff9..c16d259b 100644 --- a/src/screen.h +++ b/src/screen.h @@ -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. */ diff --git a/src/types.h b/src/types.h index a7713dc1..c3b6d928 100644 --- a/src/types.h +++ b/src/types.h @@ -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; @@ -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) { @@ -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 From f42a6fc0e8d153d7eca5c86251942210e03717b7 Mon Sep 17 00:00:00 2001 From: fjlj Date: Sat, 21 Dec 2019 03:30:24 -0800 Subject: [PATCH 02/18] update readme for fork --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 18ed3cd6..48093ba4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +This properly fixes the multi-monitor support for windows(tested only on 10, assuming 7+ will work)

+Also supports user defined speed of smooth mouse movement (original randomness updated to alter a bit based on distance)

+=================Original ReadMe To Follow==================

From fa62495362d6bcf4356d59462962c7ae83b4d4f3 Mon Sep 17 00:00:00 2001 From: fjlj Date: Sat, 21 Dec 2019 05:21:17 -0800 Subject: [PATCH 03/18] Revert "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" This reverts commit 7b1c5fb6c10faf5a3f6721e53c09dc8e86e6a97f. --- src/mouse.c | 54 +++++++++++++++++--------------------------------- src/mouse.h | 4 ++-- src/robotjs.cc | 8 ++++---- src/screen.c | 8 ++++---- src/screen.h | 2 +- src/types.h | 15 -------------- 6 files changed, 29 insertions(+), 62 deletions(-) diff --git a/src/mouse.c b/src/mouse.c index 1c4641bd..e61e8b7c 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -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, bool sm) +void moveMouse(MMSignedPoint point) { #if defined(IS_MACOSX) CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, @@ -128,20 +128,13 @@ void moveMouse(MMSignedPoint point, bool sm) if(vscreenWidth<0 || vscreenHeight<0) updateScreenMetrics(); - 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; - } + + //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); + INPUT mouseInput = {0}; mouseInput.type = INPUT_MOUSE; mouseInput.mi.dx = x; @@ -165,11 +158,11 @@ void dragMouse(MMSignedPoint point, const MMMouseButton button) CGEventPost(kCGSessionEventTap, drag); CFRelease(drag); #else - moveMouse(point,false); + moveMouse(point); #endif } -MMSignedPoint getMousePos() +MMPoint getMousePos() { #if defined(IS_MACOSX) CGEventRef event = CGEventCreate(NULL); @@ -191,13 +184,8 @@ MMSignedPoint 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)) - 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); + return MMPointFromPOINT(point); #endif } @@ -382,18 +370,15 @@ 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) { - MMSignedPoint pos = getMousePos(); - MMSignedSize screenSize = getMainDisplaySize(); + MMPoint pos = getMousePos(); + MMSize 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; @@ -412,14 +397,11 @@ 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)) - x = MOUSE_COORD_TO_ABS(pos.x - vscreenMinX, vscreenWidth); - y = MOUSE_COORD_TO_ABS(pos.y - vscreenMinY, vscreenHeight); - moveMouse(MMSignedPointMake(x,y),true); + moveMouse(MMSignedPointMake((int32_t)pos.x, (int32_t)pos.y)); /* Wait 1 - (speed) milliseconds. */ - microsleep(DEADBEEF_UNIFORM((min(0.7,speed) + (1-(distance / ((bdist + 0.0001) * 2)))), (max(0.7, speed) - (distance / ((bdist + 0.0001) * 1.5))))); + microsleep(DEADBEEF_UNIFORM(0.7, speed)); } return true; diff --git a/src/mouse.h b/src/mouse.h index 4b3c2565..764f876c 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -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, bool sm); +void moveMouse(MMSignedPoint point); /* 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. @@ -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. */ -MMSignedPoint getMousePos(void); +MMPoint getMousePos(void); /* Holds down or releases the mouse with the given button in the current * position. */ diff --git a/src/robotjs.cc b/src/robotjs.cc index 1596fee7..8aadd5d1 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -107,7 +107,7 @@ NAN_METHOD(moveMouse) MMSignedPoint point; point = MMSignedPointMake(x, y); - moveMouse(point,false); + moveMouse(point); microsleep(mouseDelay); info.GetReturnValue().Set(Nan::New(1)); @@ -140,7 +140,7 @@ NAN_METHOD(moveMouseSmooth) NAN_METHOD(getMousePos) { - MMSignedPoint pos = getMousePos(); + MMPoint pos = getMousePos(); //Return object with .x and .y. Local obj = Nan::New(); @@ -689,7 +689,7 @@ NAN_METHOD(getPixelColor) NAN_METHOD(getScreenSize) { //Get display size. - MMSignedSize displaySize = getMainDisplaySize(); + MMSize displaySize = getMainDisplaySize(); //Create our return object. Local obj = Nan::New(); @@ -746,7 +746,7 @@ NAN_METHOD(captureScreen) y = 0; //Get screen size. - MMSignedSize displaySize = getMainDisplaySize(); + MMSize displaySize = getMainDisplaySize(); w = displaySize.width; h = displaySize.height; } diff --git a/src/screen.c b/src/screen.c index 7ffe5cb6..e43b6fda 100644 --- a/src/screen.c +++ b/src/screen.c @@ -8,7 +8,7 @@ #include "xdisplay.h" #endif -MMSignedSize getMainDisplaySize(void) +MMSize getMainDisplaySize(void) { #if defined(IS_MACOSX) CGDirectDisplayID displayID = CGMainDisplayID(); @@ -21,13 +21,13 @@ MMSignedSize getMainDisplaySize(void) return MMSizeMake((size_t)DisplayWidth(display, screen), (size_t)DisplayHeight(display, screen)); #elif defined(IS_WINDOWS) - return MMSignedSizeMake((size_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), - (size_t)GetSystemMetrics(SM_CYVIRTUALSCREEN)); + return MMSizeMake((size_t)GetSystemMetrics(SM_CXSCREEN), + (size_t)GetSystemMetrics(SM_CYSCREEN)); #endif } bool pointVisibleOnMainDisplay(MMPoint point) { - MMSignedSize displaySize = getMainDisplaySize(); + MMSize displaySize = getMainDisplaySize(); return point.x < displaySize.width && point.y < displaySize.height; } diff --git a/src/screen.h b/src/screen.h index c16d259b..68860ff9 100644 --- a/src/screen.h +++ b/src/screen.h @@ -16,7 +16,7 @@ extern "C" #endif /* Returns the size of the main display. */ -MMSignedSize getMainDisplaySize(void); +MMSize getMainDisplaySize(void); /* Convenience function that returns whether the given point is in the bounds * of the main screen. */ diff --git a/src/types.h b/src/types.h index c3b6d928..a7713dc1 100644 --- a/src/types.h +++ b/src/types.h @@ -31,13 +31,6 @@ struct _MMSize { typedef struct _MMSize MMSize; -struct _MMSignedSize { - int32_t width; - int32_t height; -}; - -typedef struct _MMSignedSize MMSignedSize; - struct _MMRect { MMPoint origin; MMSize size; @@ -68,13 +61,6 @@ 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) { @@ -97,7 +83,6 @@ 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 From a23f8eedb3c3d6474b750a9641038b36cd3046a0 Mon Sep 17 00:00:00 2001 From: fjlj Date: Sat, 21 Dec 2019 05:31:36 -0800 Subject: [PATCH 04/18] cleanup solution for moveMouseSmooth/smoothlyMoveMouse multi-monitor support. properly grab virtualdesk size not just primary display size. add a bit of distance based speed modifier for this as well. --- src/mouse.c | 24 +++++++++++++----------- src/mouse.h | 2 +- src/robotjs.cc | 6 +++--- src/screen.c | 8 ++++---- src/screen.h | 2 +- src/types.h | 15 +++++++++++++++ 6 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/mouse.c b/src/mouse.c index e61e8b7c..2d4d4804 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -132,8 +132,8 @@ void moveMouse(MMSignedPoint point) //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 = MOUSE_COORD_TO_ABS(point.x - vscreenMinX, vscreenWidth); + int32_t y = MOUSE_COORD_TO_ABS(point.y - vscreenMinY, vscreenHeight); INPUT mouseInput = {0}; mouseInput.type = INPUT_MOUSE; @@ -162,7 +162,7 @@ void dragMouse(MMSignedPoint point, const MMMouseButton button) #endif } -MMPoint getMousePos() +MMSignedPoint getMousePos() { #if defined(IS_MACOSX) CGEventRef event = CGEventCreate(NULL); @@ -185,7 +185,7 @@ MMPoint getMousePos() POINT point; GetCursorPos(&point); - return MMPointFromPOINT(point); + return MMSignedPointFromPOINT(point); #endif } @@ -370,15 +370,17 @@ 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; - + 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; @@ -398,10 +400,10 @@ bool smoothlyMoveMouse(MMPoint endPoint,double speed) return false; } - moveMouse(MMSignedPointMake((int32_t)pos.x, (int32_t)pos.y)); + moveMouse(MMSignedPointMake(pos.x, pos.y)); /* 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; diff --git a/src/mouse.h b/src/mouse.h index 764f876c..a8135ffa 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -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. */ diff --git a/src/robotjs.cc b/src/robotjs.cc index 8aadd5d1..716e1bbd 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -140,7 +140,7 @@ NAN_METHOD(moveMouseSmooth) NAN_METHOD(getMousePos) { - MMPoint pos = getMousePos(); + MMSignedPoint pos = getMousePos(); //Return object with .x and .y. Local obj = Nan::New(); @@ -689,7 +689,7 @@ NAN_METHOD(getPixelColor) NAN_METHOD(getScreenSize) { //Get display size. - MMSize displaySize = getMainDisplaySize(); + MMSignedSize displaySize = getMainDisplaySize(); //Create our return object. Local obj = Nan::New(); @@ -746,7 +746,7 @@ NAN_METHOD(captureScreen) y = 0; //Get screen size. - MMSize displaySize = getMainDisplaySize(); + MMSignedSize displaySize = getMainDisplaySize(); w = displaySize.width; h = displaySize.height; } diff --git a/src/screen.c b/src/screen.c index e43b6fda..7ffe5cb6 100644 --- a/src/screen.c +++ b/src/screen.c @@ -8,7 +8,7 @@ #include "xdisplay.h" #endif -MMSize getMainDisplaySize(void) +MMSignedSize getMainDisplaySize(void) { #if defined(IS_MACOSX) CGDirectDisplayID displayID = CGMainDisplayID(); @@ -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; } diff --git a/src/screen.h b/src/screen.h index 68860ff9..c16d259b 100644 --- a/src/screen.h +++ b/src/screen.h @@ -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. */ diff --git a/src/types.h b/src/types.h index a7713dc1..c3b6d928 100644 --- a/src/types.h +++ b/src/types.h @@ -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; @@ -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) { @@ -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 From 3804e69cd43da770b600e89ca95ab83325f615ca Mon Sep 17 00:00:00 2001 From: fjlj Date: Wed, 25 Dec 2019 06:36:15 -0800 Subject: [PATCH 05/18] update readme to reflect multimonitor support --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 48093ba4..c5e49d3c 100644 --- a/README.md +++ b/README.md @@ -156,8 +156,7 @@ Soon! This is a bit more complicated than the rest of the features, so I saved i We've been implementing keys as we need them. Feel free to create an issue or submit a pull request! #### How about multi-monitor support? - -The library doesn't have explicit multi-monitor support, so anything that works is kind of on accident. Subscribe to [#88](https://github.com/octalmage/robotjs/issues/88) for updates. +Multiple monitor support working. Tested in windows only, need additional feedback for mac/nix. For any other questions please [submit an issue](https://github.com/octalmage/robotjs/issues/new). From 16db5958d2e9ff9c648099d00305ab324494ded7 Mon Sep 17 00:00:00 2001 From: Dominik Klotz Date: Fri, 2 Oct 2020 16:14:26 +0200 Subject: [PATCH 06/18] Fix linux build --- src/mouse.c | 9 +++++++-- src/screen.c | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/mouse.c b/src/mouse.c index 2d4d4804..a8676671 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -126,8 +126,10 @@ void moveMouse(MMSignedPoint point) XSync(display, false); #elif defined(IS_WINDOWS) + #if defined(IS_MACOSX) if(vscreenWidth<0 || vscreenHeight<0) updateScreenMetrics(); + #endif //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)) @@ -180,7 +182,7 @@ MMSignedPoint getMousePos() XQueryPointer(display, XDefaultRootWindow(display), &garb1, &garb2, &x, &y, &garb_x, &garb_y, &more_garbage); - return MMPointMake(x, y); + return MMSignedPointMake(x, y); #elif defined(IS_WINDOWS) POINT point; GetCursorPos(&point); @@ -376,8 +378,11 @@ bool smoothlyMoveMouse(MMPoint endPoint, double speed) MMSignedSize screenSize = getMainDisplaySize(); double velo_x = 0.0, velo_y = 0.0; double distance; + + #if defined(IS_MACOSX) if (vscreenWidth < 0 || vscreenHeight < 0) updateScreenMetrics(); + #endif 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) { @@ -403,7 +408,7 @@ bool smoothlyMoveMouse(MMPoint endPoint, double speed) moveMouse(MMSignedPointMake(pos.x, pos.y)); /* Wait 1 - (speed) milliseconds. */ - microsleep(DEADBEEF_UNIFORM((min(0.7,speed) + (1-(distance / ((bdist + 0.0001) * 2)))), (max(0.7, speed) - (distance / ((bdist + 0.0001) * 1.5))))); + microsleep(DEADBEEF_UNIFORM((fmin(0.7,speed) + (1-(distance / ((bdist + 0.0001) * 2)))), (fmax(0.7, speed) - (distance / ((bdist + 0.0001) * 1.5))))); } return true; diff --git a/src/screen.c b/src/screen.c index 7ffe5cb6..a2ddbc9a 100644 --- a/src/screen.c +++ b/src/screen.c @@ -12,13 +12,13 @@ MMSignedSize getMainDisplaySize(void) { #if defined(IS_MACOSX) CGDirectDisplayID displayID = CGMainDisplayID(); - return MMSizeMake(CGDisplayPixelsWide(displayID), + return MMSignedSizeMake(CGDisplayPixelsWide(displayID), CGDisplayPixelsHigh(displayID)); #elif defined(USE_X11) Display *display = XGetMainDisplay(); const int screen = DefaultScreen(display); - return MMSizeMake((size_t)DisplayWidth(display, screen), + return MMSignedSizeMake((size_t)DisplayWidth(display, screen), (size_t)DisplayHeight(display, screen)); #elif defined(IS_WINDOWS) return MMSignedSizeMake((size_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), From 0e56257098819b8e29b23b325351dd414ac5da18 Mon Sep 17 00:00:00 2001 From: Dominik Klotz Date: Fri, 2 Oct 2020 16:23:33 +0200 Subject: [PATCH 07/18] fix build for mac --- src/mouse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mouse.c b/src/mouse.c index cfb8d8f3..770c3e2d 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -171,7 +171,7 @@ MMSignedPoint getMousePos() CGPoint point = CGEventGetLocation(event); CFRelease(event); - return MMPointFromCGPoint(point); + return MMSignedPointFromCGPoint(point); #elif defined(USE_X11) int x, y; /* This is all we care about. Seriously. */ Window garb1, garb2; /* Why you can't specify NULL as a parameter */ @@ -380,7 +380,7 @@ bool smoothlyMoveMouse(MMPoint endPoint, double speed) double velo_x = 0.0, velo_y = 0.0; double distance; - #if defined(IS_MACOSX) + #if defined(IS_WINDOWS) if (vscreenWidth < 0 || vscreenHeight < 0) updateScreenMetrics(); #endif From 0227899c87ad69876d5f1761275908e89ed021d2 Mon Sep 17 00:00:00 2001 From: Dominik Klotz Date: Fri, 2 Oct 2020 16:25:19 +0200 Subject: [PATCH 08/18] fix build for mac --- src/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.h b/src/types.h index c3b6d928..8b8b46f2 100644 --- a/src/types.h +++ b/src/types.h @@ -92,7 +92,7 @@ H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height) #define MMPointFromCGPoint(p) MMPointMake((size_t)(p).x, (size_t)(p).y) #define CGPointFromMMSignedPoint(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y) -#define MMSignedPointFromCGPoint(p) MMPointMake((int32_t)(p).x, (int32_t)(p).y) +#define MMSignedPointFromCGPoint(p) MMSignedPointMake((int32_t)(p).x, (int32_t)(p).y) #elif defined(IS_WINDOWS) From c82079ec5a365c4f5105db8a2abf3ebe5445222a Mon Sep 17 00:00:00 2001 From: Programmnix Date: Mon, 5 Oct 2020 11:23:27 +0200 Subject: [PATCH 09/18] Dirty hack to allow mouth move on multiple screens on mac --- src/mouse.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/mouse.c b/src/mouse.c index 770c3e2d..b02a8203 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -400,11 +400,18 @@ bool smoothlyMoveMouse(MMPoint endPoint, double speed) pos.x += floor(velo_x + 0.5); pos.y += floor(velo_y + 0.5); + + #if defined(IS_MACOSX) + /** + * Dirty hack for move mouse smooth on mac with multiple displays + */ + #else /* Make sure we are in the screen boundaries! * (Strange things will happen if we are not.) */ if (pos.x >= screenSize.width || pos.y >= screenSize.height) { return false; } + #endif moveMouse(MMSignedPointMake(pos.x, pos.y)); From 9c4cb1c1936b5f9385afaae76a2aa3874f6b810d Mon Sep 17 00:00:00 2001 From: Dominik Klotz Date: Tue, 6 Oct 2020 09:15:02 +0200 Subject: [PATCH 10/18] migrate smoothlyMoveMouse to MMSignedPoint --- src/mouse.c | 21 ++++++++------------- src/mouse.h | 2 +- src/robotjs.cc | 4 ++-- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/mouse.c b/src/mouse.c index b02a8203..28003e46 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -126,10 +126,8 @@ void moveMouse(MMSignedPoint point) XSync(display, false); #elif defined(IS_WINDOWS) - #if defined(IS_MACOSX) if(vscreenWidth<0 || vscreenHeight<0) updateScreenMetrics(); - #endif //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)) @@ -373,7 +371,7 @@ static double crude_hypot(double x, double y) return ((M_SQRT2 - 1.0) * small) + big; } -bool smoothlyMoveMouse(MMPoint endPoint, double speed) +bool smoothlyMoveMouse(MMSignedPoint endPoint, double speed) { MMSignedPoint pos = getMousePos(); MMSignedSize screenSize = getMainDisplaySize(); @@ -401,18 +399,15 @@ bool smoothlyMoveMouse(MMPoint endPoint, double speed) pos.y += floor(velo_y + 0.5); - #if defined(IS_MACOSX) - /** - * Dirty hack for move mouse smooth on mac with multiple displays - */ - #else + /** + * Dirty hack for move mouse smooth on all displays with multiple displays + */ /* Make sure we are in the screen boundaries! * (Strange things will happen if we are not.) */ - if (pos.x >= screenSize.width || pos.y >= screenSize.height) { - return false; - } - #endif - + // if (pos.x >= screenSize.width || pos.y >= screenSize.height) { + // return false; + // } + moveMouse(MMSignedPointMake(pos.x, pos.y)); /* Wait 1 - (speed) milliseconds. */ diff --git a/src/mouse.h b/src/mouse.h index a8135ffa..30d5ac75 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -79,7 +79,7 @@ void dragMouse(MMSignedPoint point, const MMMouseButton button); * * Returns false if unsuccessful (i.e. a point was hit that is outside of the * screen boundaries), or true if successful. */ -bool smoothlyMoveMouse(MMPoint point,double speed); +bool smoothlyMoveMouse(MMSignedPoint point,double speed); /* Returns the coordinates of the mouse on the current screen. */ MMSignedPoint getMousePos(void); diff --git a/src/robotjs.cc b/src/robotjs.cc index 8ecf114f..cde7f47d 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -122,8 +122,8 @@ NAN_METHOD(moveMouseSmooth) size_t x = Nan::To(info[0]).FromJust(); size_t y = Nan::To(info[1]).FromJust(); - MMPoint point; - point = MMPointMake(x, y); + MMSignedPoint point; + point = MMSignedPointMake(x, y); if (info.Length() == 3) { size_t speed = Nan::To(info[2]).FromJust(); From d9e08085b4f26ab3e7a7d763843aab7c4a5d057b Mon Sep 17 00:00:00 2001 From: Dominik Klotz Date: Tue, 6 Oct 2020 21:22:35 +0200 Subject: [PATCH 11/18] Use MMSingedPoint for smoothlyMoveMouse --- index.d.ts | 1 + src/mouse.c | 12 +++++------- src/mouse.h | 2 +- src/robotjs.cc | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/index.d.ts b/index.d.ts index 9e2b23fd..3c228a3a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -29,5 +29,6 @@ export function scrollMouse(x: number, y: number) : void export function getMousePos(): { x: number, y: number } export function getPixelColor(x: number, y: number): string export function getScreenSize(): { width: number, height: number } +export function getScreenSizes(): Array<{ left: number, top: number, right: number, bottom: number }> export var screen: Screen diff --git a/src/mouse.c b/src/mouse.c index b02a8203..e09aebb0 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -126,10 +126,8 @@ void moveMouse(MMSignedPoint point) XSync(display, false); #elif defined(IS_WINDOWS) - #if defined(IS_MACOSX) if(vscreenWidth<0 || vscreenHeight<0) updateScreenMetrics(); - #endif //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)) @@ -139,7 +137,7 @@ void moveMouse(MMSignedPoint point) INPUT mouseInput = {0}; mouseInput.type = INPUT_MOUSE; - mouseInput.mi.dx = x; + mouseInput.mi.dx = x - 100; mouseInput.mi.dy = y; mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK; mouseInput.mi.time = 0; //System will provide the timestamp @@ -373,7 +371,7 @@ static double crude_hypot(double x, double y) return ((M_SQRT2 - 1.0) * small) + big; } -bool smoothlyMoveMouse(MMPoint endPoint, double speed) +bool smoothlyMoveMouse(MMSignedPoint endPoint, double speed) { MMSignedPoint pos = getMousePos(); MMSignedSize screenSize = getMainDisplaySize(); @@ -408,9 +406,9 @@ bool smoothlyMoveMouse(MMPoint endPoint, double speed) #else /* Make sure we are in the screen boundaries! * (Strange things will happen if we are not.) */ - if (pos.x >= screenSize.width || pos.y >= screenSize.height) { - return false; - } + //if (pos.x >= screenSize.width || pos.y >= screenSize.height) { + // return false; + //} #endif moveMouse(MMSignedPointMake(pos.x, pos.y)); diff --git a/src/mouse.h b/src/mouse.h index a8135ffa..30d5ac75 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -79,7 +79,7 @@ void dragMouse(MMSignedPoint point, const MMMouseButton button); * * Returns false if unsuccessful (i.e. a point was hit that is outside of the * screen boundaries), or true if successful. */ -bool smoothlyMoveMouse(MMPoint point,double speed); +bool smoothlyMoveMouse(MMSignedPoint point,double speed); /* Returns the coordinates of the mouse on the current screen. */ MMSignedPoint getMousePos(void); diff --git a/src/robotjs.cc b/src/robotjs.cc index 8ecf114f..91bb75c9 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -14,12 +14,32 @@ #include "xdisplay.h" #endif +#include +#include + using namespace v8; //Global delays. int mouseDelay = 10; int keyboardDelay = 10; +struct MonitorRects +{ + std::vector rcMonitors; + + static BOOL CALLBACK MonitorEnum(HMONITOR hMon,HDC hdc,LPRECT lprcMonitor,LPARAM pData) + { + MonitorRects* pThis = reinterpret_cast(pData); + pThis->rcMonitors.push_back(*lprcMonitor); + return TRUE; + } + + MonitorRects() + { + EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this); + } +}; + /* __ __ | \/ | ___ _ _ ___ ___ @@ -122,8 +142,8 @@ NAN_METHOD(moveMouseSmooth) size_t x = Nan::To(info[0]).FromJust(); size_t y = Nan::To(info[1]).FromJust(); - MMPoint point; - point = MMPointMake(x, y); + MMSignedPoint point; + point = MMSignedPointMake(x, y); if (info.Length() == 3) { size_t speed = Nan::To(info[2]).FromJust(); @@ -710,6 +730,7 @@ NAN_METHOD(getPixelColor) info.GetReturnValue().Set(Nan::New(hex).ToLocalChecked()); } + NAN_METHOD(getScreenSize) { //Get display size. @@ -724,6 +745,28 @@ NAN_METHOD(getScreenSize) info.GetReturnValue().Set(obj); } + +NAN_METHOD(getScreenSizes) +{ + + MonitorRects monitors; + + Local a = Nan::New(monitors.rcMonitors.size()); + + for (int i = 0; i < monitors.rcMonitors.size(); ++i){ + std::cout << monitors.rcMonitors[i].left << " " << monitors.rcMonitors[i].right << " " << monitors.rcMonitors[i].top << " " << monitors.rcMonitors[i].bottom << "\n"; + //Create our return object. + Local obj = Nan::New(); + Nan::Set(obj, Nan::New("left").ToLocalChecked(), Nan::New(monitors.rcMonitors[i].left)); + Nan::Set(obj, Nan::New("top").ToLocalChecked(), Nan::New(monitors.rcMonitors[i].top)); + Nan::Set(obj, Nan::New("right").ToLocalChecked(), Nan::New(monitors.rcMonitors[i].right)); + Nan::Set(obj, Nan::New("bottom").ToLocalChecked(), Nan::New(monitors.rcMonitors[i].bottom)); + Nan::Set(a, i, obj); + } + //Return our object with .width and .height. + info.GetReturnValue().Set(a); +} + NAN_METHOD(getXDisplayName) { #if defined(USE_X11) @@ -917,6 +960,9 @@ NAN_MODULE_INIT(InitAll) Nan::Set(target, Nan::New("getScreenSize").ToLocalChecked(), Nan::GetFunction(Nan::New(getScreenSize)).ToLocalChecked()); + + Nan::Set(target, Nan::New("getScreenSizes").ToLocalChecked(), + Nan::GetFunction(Nan::New(getScreenSizes)).ToLocalChecked()); Nan::Set(target, Nan::New("captureScreen").ToLocalChecked(), Nan::GetFunction(Nan::New(captureScreen)).ToLocalChecked()); From 8b6e2d36fd45a895100855686631aee2ce88d93b Mon Sep 17 00:00:00 2001 From: Dominik Klotz Date: Tue, 6 Oct 2020 21:32:53 +0200 Subject: [PATCH 12/18] Resolve build conflicts --- index.d.ts | 2 +- src/robotjs.cc | 57 ++++++++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/index.d.ts b/index.d.ts index 3c228a3a..f262dc11 100644 --- a/index.d.ts +++ b/index.d.ts @@ -29,6 +29,6 @@ export function scrollMouse(x: number, y: number) : void export function getMousePos(): { x: number, y: number } export function getPixelColor(x: number, y: number): string export function getScreenSize(): { width: number, height: number } -export function getScreenSizes(): Array<{ left: number, top: number, right: number, bottom: number }> +export function getScreenRects(): Array<{ left: number, top: number, right: number, bottom: number }> export var screen: Screen diff --git a/src/robotjs.cc b/src/robotjs.cc index 91bb75c9..c7737dbc 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -14,8 +14,28 @@ #include "xdisplay.h" #endif -#include -#include + +#if defined(IS_WINDOWS) + #include + + struct MonitorRects + { + std::vector rcMonitors; + + static BOOL CALLBACK MonitorEnum(HMONITOR hMon,HDC hdc,LPRECT lprcMonitor,LPARAM pData) + { + MonitorRects* pThis = reinterpret_cast(pData); + pThis->rcMonitors.push_back(*lprcMonitor); + return TRUE; + } + + MonitorRects() + { + EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this); + } + }; +#endif + using namespace v8; @@ -23,23 +43,6 @@ using namespace v8; int mouseDelay = 10; int keyboardDelay = 10; -struct MonitorRects -{ - std::vector rcMonitors; - - static BOOL CALLBACK MonitorEnum(HMONITOR hMon,HDC hdc,LPRECT lprcMonitor,LPARAM pData) - { - MonitorRects* pThis = reinterpret_cast(pData); - pThis->rcMonitors.push_back(*lprcMonitor); - return TRUE; - } - - MonitorRects() - { - EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this); - } -}; - /* __ __ | \/ | ___ _ _ ___ ___ @@ -746,16 +749,16 @@ NAN_METHOD(getScreenSize) } -NAN_METHOD(getScreenSizes) + +NAN_METHOD(getScreenRects) { + #if defined(IS_WINDOWS) MonitorRects monitors; Local a = Nan::New(monitors.rcMonitors.size()); for (int i = 0; i < monitors.rcMonitors.size(); ++i){ - std::cout << monitors.rcMonitors[i].left << " " << monitors.rcMonitors[i].right << " " << monitors.rcMonitors[i].top << " " << monitors.rcMonitors[i].bottom << "\n"; - //Create our return object. Local obj = Nan::New(); Nan::Set(obj, Nan::New("left").ToLocalChecked(), Nan::New(monitors.rcMonitors[i].left)); Nan::Set(obj, Nan::New("top").ToLocalChecked(), Nan::New(monitors.rcMonitors[i].top)); @@ -763,10 +766,14 @@ NAN_METHOD(getScreenSizes) Nan::Set(obj, Nan::New("bottom").ToLocalChecked(), Nan::New(monitors.rcMonitors[i].bottom)); Nan::Set(a, i, obj); } - //Return our object with .width and .height. + info.GetReturnValue().Set(a); + #else + Nan::ThrowError("getScreenRects is not supported on your OS"); + #endif } + NAN_METHOD(getXDisplayName) { #if defined(USE_X11) @@ -961,8 +968,8 @@ NAN_MODULE_INIT(InitAll) Nan::Set(target, Nan::New("getScreenSize").ToLocalChecked(), Nan::GetFunction(Nan::New(getScreenSize)).ToLocalChecked()); - Nan::Set(target, Nan::New("getScreenSizes").ToLocalChecked(), - Nan::GetFunction(Nan::New(getScreenSizes)).ToLocalChecked()); + Nan::Set(target, Nan::New("getScreenRects").ToLocalChecked(), + Nan::GetFunction(Nan::New(getScreenRects)).ToLocalChecked()); Nan::Set(target, Nan::New("captureScreen").ToLocalChecked(), Nan::GetFunction(Nan::New(captureScreen)).ToLocalChecked()); From 00d53b3a398cdd0660a84e942093c584525847be Mon Sep 17 00:00:00 2001 From: Dominik Klotz Date: Fri, 9 Oct 2020 16:46:26 +0200 Subject: [PATCH 13/18] Fix min version for xcode --- binding.gyp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/binding.gyp b/binding.gyp index e0b74437..353c2bcf 100644 --- a/binding.gyp +++ b/binding.gyp @@ -21,6 +21,9 @@ 'System/Library/Frameworks/ApplicationServices.framework/Headers', 'System/Library/Frameworks/OpenGL.framework/Headers', ], + 'xcode_settings': { + 'MACOSX_DEPLOYMENT_TARGET': '10.12', + }, 'link_settings': { 'libraries': [ '-framework Carbon', From 1372ef59f3191e627bff6397ab1a70acc49dae31 Mon Sep 17 00:00:00 2001 From: Dominik Klotz Date: Tue, 1 Feb 2022 15:47:40 +0100 Subject: [PATCH 14/18] Upgrade dependencies --- package.json | 10 +++++----- src/mouse.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 6eb19ded..c63bf5a5 100644 --- a/package.json +++ b/package.json @@ -42,14 +42,14 @@ }, "homepage": "https://github.com/octalmage/robotjs", "dependencies": { - "nan": "^2.14.0", - "prebuild-install": "^5.3.3" + "nan": "^2.15.0", + "prebuild-install": "^7.0.1" }, "devDependencies": { - "tape": "^4.8.0", - "jasmine": "^2.99.0", + "tape": "^5.5.0", + "jasmine": "^4.0.2", "prebuild": "^9.1.1", - "run-script-os": "^1.0.3", + "run-script-os": "^1.0.6", "targetpractice": "0.0.7" } } diff --git a/src/mouse.c b/src/mouse.c index ff95bc93..f1c4f30f 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -137,7 +137,7 @@ void moveMouse(MMSignedPoint point) INPUT mouseInput = {0}; mouseInput.type = INPUT_MOUSE; - mouseInput.mi.dx = x - 100; + mouseInput.mi.dx = x; mouseInput.mi.dy = y; mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK; mouseInput.mi.time = 0; //System will provide the timestamp From 952bfa21affe59cfe108156cc756185b5c68de48 Mon Sep 17 00:00:00 2001 From: adi-wan Date: Mon, 14 Mar 2022 21:32:27 +0100 Subject: [PATCH 15/18] ignore vscode settings in source control --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ec4d2a83..cd54133b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build/ node_modules/ prebuilds/ -/.idea \ No newline at end of file +/.idea +/.vscode From b3ad6ec3e987cac5da4f33d1df49096661bf3743 Mon Sep 17 00:00:00 2001 From: adi-wan Date: Mon, 14 Mar 2022 22:35:26 +0100 Subject: [PATCH 16/18] allow negative coords as origin of screen --- src/robotjs.cc | 8 ++++---- src/types.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/robotjs.cc b/src/robotjs.cc index c7737dbc..a231cca0 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -712,8 +712,8 @@ NAN_METHOD(getPixelColor) MMBitmapRef bitmap; MMRGBHex color; - size_t x = Nan::To(info[0]).FromJust(); - size_t y = Nan::To(info[1]).FromJust(); + int32_t x = Nan::To(info[0]).FromJust(); + int32_t y = Nan::To(info[1]).FromJust(); if (!pointVisibleOnMainDisplay(MMPointMake(x, y))) { @@ -797,8 +797,8 @@ NAN_METHOD(setXDisplayName) NAN_METHOD(captureScreen) { - size_t x; - size_t y; + int32_t x; + int32_t y; size_t w; size_t h; diff --git a/src/types.h b/src/types.h index 8b8b46f2..d59a5636 100644 --- a/src/types.h +++ b/src/types.h @@ -39,7 +39,7 @@ struct _MMSignedSize { typedef struct _MMSignedSize MMSignedSize; struct _MMRect { - MMPoint origin; + MMSignedPoint origin; MMSize size; }; @@ -76,10 +76,10 @@ H_INLINE MMSignedSize MMSignedSizeMake(int32_t width, int32_t height) return size; } -H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height) +H_INLINE MMRect MMRectMake(int32_t x, int32_t y, size_t width, size_t height) { MMRect rect; - rect.origin = MMPointMake(x, y); + rect.origin = MMSignedPointMake(x, y); rect.size = MMSizeMake(width, height); return rect; } From eb13e5c613f688f3fdbaf09537f1b25aacf654de Mon Sep 17 00:00:00 2001 From: adi-wan Date: Tue, 15 Mar 2022 00:46:05 +0100 Subject: [PATCH 17/18] add multi-screen support for captureScreen on mac --- src/screen.c | 36 ++++++++++++++++++++++++++++++++++++ src/screen.h | 4 ++++ src/screengrab.c | 12 +++++++----- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/screen.c b/src/screen.c index a2ddbc9a..db23b02c 100644 --- a/src/screen.c +++ b/src/screen.c @@ -8,6 +8,42 @@ #include "xdisplay.h" #endif +#if defined(IS_MACOSX) +uint32_t getIDOfDisplayWithRect(MMRect rect) +{ + CGError cgErr; + CGDisplayCount displayCount; + CGDisplayCount maxDisplays = 1; + CGDirectDisplayID onlineDisplays[1]; + CGRect cgRect = CGRectMake(rect.origin.x, + rect.origin.y, + rect.size.width, + rect.size.height); + + // If CGGetOnlineDisplayList() is not called, CGGetDisplaysWithRect() fails + CGGetOnlineDisplayList(maxDisplays, onlineDisplays, &displayCount); + cgErr = CGGetDisplaysWithRect(cgRect, maxDisplays, onlineDisplays, &displayCount); + + if (cgErr != kCGErrorSuccess) + { + fprintf(stderr, "CGGetDisplaysWithRect: error %d.\n", cgErr); + exit(1); + } + if (displayCount == 0) + { + fprintf(stderr, + "No display with rect with origin (%d, %d), width %d and height %d.\n", + (int) cgRect.origin.x, + (int) cgRect.origin.y, + (int) cgRect.size.width, + (int) cgRect.size.height); + exit(1); + } + + return onlineDisplays[0]; +}; +#endif + MMSignedSize getMainDisplaySize(void) { #if defined(IS_MACOSX) diff --git a/src/screen.h b/src/screen.h index c16d259b..ebd370e1 100644 --- a/src/screen.h +++ b/src/screen.h @@ -15,6 +15,10 @@ extern "C" { #endif +#if defined(IS_MACOSX) + uint32_t getIDOfDisplayWithRect(MMRect rect); +#endif + /* Returns the size of the main display. */ MMSignedSize getMainDisplaySize(void); diff --git a/src/screengrab.c b/src/screengrab.c index 619020b6..f5a85f2e 100644 --- a/src/screengrab.c +++ b/src/screengrab.c @@ -4,6 +4,7 @@ #include /* malloc() */ #if defined(IS_MACOSX) + #include "screen.h" #include #include #include @@ -23,13 +24,14 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect) uint8_t *buffer = NULL; size_t bufferSize = 0; - CGDirectDisplayID displayID = CGMainDisplayID(); + CGDirectDisplayID displayID = getIDOfDisplayWithRect(rect); + CGRect bounds = CGDisplayBounds(displayID); CGImageRef image = CGDisplayCreateImageForRect(displayID, - CGRectMake(rect.origin.x, - rect.origin.y, - rect.size.width, - rect.size.height)); + CGRectMake(rect.origin.x - (int32_t) bounds.origin.x, + rect.origin.y - (int32_t) bounds.origin.y, + rect.size.width, + rect.size.height)); if (!image) { return NULL; } From 82c68e5708bcd9af451438622e32634d10f81df8 Mon Sep 17 00:00:00 2001 From: adi-wan Date: Tue, 15 Mar 2022 00:50:41 +0100 Subject: [PATCH 18/18] make code changes more consistent to rest of code --- src/screen.c | 16 ++++++++-------- src/screengrab.c | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/screen.c b/src/screen.c index db23b02c..c977688b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -16,9 +16,9 @@ uint32_t getIDOfDisplayWithRect(MMRect rect) CGDisplayCount maxDisplays = 1; CGDirectDisplayID onlineDisplays[1]; CGRect cgRect = CGRectMake(rect.origin.x, - rect.origin.y, - rect.size.width, - rect.size.height); + rect.origin.y, + rect.size.width, + rect.size.height); // If CGGetOnlineDisplayList() is not called, CGGetDisplaysWithRect() fails CGGetOnlineDisplayList(maxDisplays, onlineDisplays, &displayCount); @@ -32,11 +32,11 @@ uint32_t getIDOfDisplayWithRect(MMRect rect) if (displayCount == 0) { fprintf(stderr, - "No display with rect with origin (%d, %d), width %d and height %d.\n", - (int) cgRect.origin.x, - (int) cgRect.origin.y, - (int) cgRect.size.width, - (int) cgRect.size.height); + "No display with rect with origin (%d, %d), width %d and height %d.\n", + (int) cgRect.origin.x, + (int) cgRect.origin.y, + (int) cgRect.size.width, + (int) cgRect.size.height); exit(1); } diff --git a/src/screengrab.c b/src/screengrab.c index f5a85f2e..4d08758e 100644 --- a/src/screengrab.c +++ b/src/screengrab.c @@ -28,10 +28,10 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect) CGRect bounds = CGDisplayBounds(displayID); CGImageRef image = CGDisplayCreateImageForRect(displayID, - CGRectMake(rect.origin.x - (int32_t) bounds.origin.x, - rect.origin.y - (int32_t) bounds.origin.y, - rect.size.width, - rect.size.height)); + CGRectMake(rect.origin.x - (int32_t) bounds.origin.x, + rect.origin.y - (int32_t) bounds.origin.y, + rect.size.width, + rect.size.height)); if (!image) { return NULL; }