From b80b20c25400ed39e94c83547ddac1e78c373044 Mon Sep 17 00:00:00 2001 From: vinvol <690908+vinvol@users.noreply.github.com> Date: Mon, 25 May 2020 21:00:28 -0400 Subject: [PATCH] Add initial support for multi-display --- index.d.ts | 1 + src/robotjs.cc | 47 +++++++++++++++++++++++++++++++++++++++++------ src/screen.c | 18 ++++++++++++++++++ src/screen.h | 3 +++ src/screengrab.c | 4 +--- src/screengrab.h | 2 +- src/types.h | 23 ++++++++++++++++++++--- test/screen.js | 6 ++++++ 8 files changed, 91 insertions(+), 13 deletions(-) diff --git a/index.d.ts b/index.d.ts index 9e2b23fd..75b7d531 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 getAllScreensSize(): { displayID: number; width: number; height: number; }[] export var screen: Screen diff --git a/src/robotjs.cc b/src/robotjs.cc index f96d98fc..56415bed 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -689,15 +689,22 @@ NAN_METHOD(getPixelColor) MMBitmapRef bitmap; MMRGBHex color; - size_t x = Nan::To(info[0]).FromJust(); - size_t y = Nan::To(info[1]).FromJust(); + float x = Nan::To(info[0]).FromJust(); + float y = Nan::To(info[1]).FromJust(); - if (!pointVisibleOnMainDisplay(MMPointMake(x, y))) + CGPoint mouse = CGPointMake(x, y); + + uint32_t count = 0; + CGDirectDisplayID displayID; + if (CGGetDisplaysWithPoint(mouse, 1, &displayID, &count) != kCGErrorSuccess) { - return Nan::ThrowError("Requested coordinates are outside the main screen's dimensions."); + return Nan::ThrowError("Could not find a display for the coordinates of the mosue."); } - bitmap = copyMMBitmapFromDisplayInRect(MMRectMake(x, y, 1, 1)); + CGRect displayPosition = CGDisplayBounds(displayID); + MMRect adjustedRect = MMRectMake(x - displayPosition.origin.x, y - displayPosition.origin.y, 1, 1); + + bitmap = copyMMBitmapFromDisplayInRect(displayID, adjustedRect); color = MMRGBHexAtPoint(bitmap, 0, 0); @@ -724,6 +731,30 @@ NAN_METHOD(getScreenSize) info.GetReturnValue().Set(obj); } +NAN_METHOD(getAllScreensSize) +{ + //Get all active display sizes. + uint32_t numDisplays = 0; + MMDisplaySize displaySizes[10]; + + getAllDisplaySize(&numDisplays, displaySizes); + + //Create our return object. + Local list = Nan::New(numDisplays); + for (uint32_t i = 0; i < numDisplays; i++) + { + Local obj = Nan::New(); + Nan::Set(obj, Nan::New("displayID").ToLocalChecked(), Nan::New(displaySizes[i].displayID)); + Nan::Set(obj, Nan::New("width").ToLocalChecked(), Nan::New(displaySizes[i].size.width)); + Nan::Set(obj, Nan::New("height").ToLocalChecked(), Nan::New(displaySizes[i].size.height)); + + Nan::Set(list, i, obj); + } + + //Return our list with many [{ width, height }, ...] + info.GetReturnValue().Set(list); +} + NAN_METHOD(getXDisplayName) { #if defined(USE_X11) @@ -775,7 +806,8 @@ NAN_METHOD(captureScreen) h = displaySize.height; } - MMBitmapRef bitmap = copyMMBitmapFromDisplayInRect(MMRectMake(x, y, w, h)); + CGDirectDisplayID displayID = CGMainDisplayID(); + MMBitmapRef bitmap = copyMMBitmapFromDisplayInRect(displayID, MMRectMake(x, y, w, h)); uint32_t bufferSize = bitmap->bytewidth * bitmap->height; Local buffer = Nan::NewBuffer((char*)bitmap->imageBuffer, bufferSize, destroyMMBitmapBuffer, NULL).ToLocalChecked(); @@ -918,6 +950,9 @@ NAN_MODULE_INIT(InitAll) Nan::Set(target, Nan::New("getScreenSize").ToLocalChecked(), Nan::GetFunction(Nan::New(getScreenSize)).ToLocalChecked()); + Nan::Set(target, Nan::New("getAllScreensSize").ToLocalChecked(), + Nan::GetFunction(Nan::New(getAllScreensSize)).ToLocalChecked()); + Nan::Set(target, Nan::New("captureScreen").ToLocalChecked(), Nan::GetFunction(Nan::New(captureScreen)).ToLocalChecked()); diff --git a/src/screen.c b/src/screen.c index e43b6fda..b86c8af3 100644 --- a/src/screen.c +++ b/src/screen.c @@ -8,6 +8,24 @@ #include "xdisplay.h" #endif +void getAllDisplaySize(uint32_t *_Nullable numDisplays, MMDisplaySize *_Nullable displaySizes) +{ +#if defined(IS_MACOSX) + + CGDirectDisplayID displays[10]; + + CGGetOnlineDisplayList(10, displays, numDisplays); + for (uint32_t i = 0; i < *numDisplays; i++) + { + displaySizes[i] = MMDisplaySizeMake( + displays[i], + CGDisplayPixelsWide(displays[i]), + CGDisplayPixelsHigh(displays[i])); + } + +#endif +} + MMSize getMainDisplaySize(void) { #if defined(IS_MACOSX) diff --git a/src/screen.h b/src/screen.h index 68860ff9..3c06fbe6 100644 --- a/src/screen.h +++ b/src/screen.h @@ -18,6 +18,9 @@ extern "C" /* Returns the size of the main display. */ MMSize getMainDisplaySize(void); +/* Returns a list of displayID, with their sizes. */ +void getAllDisplaySize(uint32_t *_Nullable numDisplays, MMDisplaySize *_Nullable displaySizes); + /* Convenience function that returns whether the given point is in the bounds * of the main screen. */ bool pointVisibleOnMainDisplay(MMPoint point); diff --git a/src/screengrab.c b/src/screengrab.c index 619020b6..adb9d943 100644 --- a/src/screengrab.c +++ b/src/screengrab.c @@ -15,7 +15,7 @@ #include #endif -MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect) +MMBitmapRef copyMMBitmapFromDisplayInRect(int32_t displayID, MMRect rect) { #if defined(IS_MACOSX) @@ -23,8 +23,6 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect) uint8_t *buffer = NULL; size_t bufferSize = 0; - CGDirectDisplayID displayID = CGMainDisplayID(); - CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(rect.origin.x, rect.origin.y, diff --git a/src/screengrab.h b/src/screengrab.h index f10be42d..26a512f7 100644 --- a/src/screengrab.h +++ b/src/screengrab.h @@ -12,7 +12,7 @@ extern "C" /* Returns a raw bitmap of screengrab of the display (to be destroyed()'d by * caller), or NULL on error. */ -MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect); +MMBitmapRef copyMMBitmapFromDisplayInRect(int32_t displayID, MMRect rect); #ifdef __cplusplus } diff --git a/src/types.h b/src/types.h index a7713dc1..1f96892a 100644 --- a/src/types.h +++ b/src/types.h @@ -32,12 +32,20 @@ struct _MMSize { typedef struct _MMSize MMSize; struct _MMRect { - MMPoint origin; + MMSignedPoint origin; MMSize size; }; typedef struct _MMRect MMRect; +struct _MMDisplaySize +{ + int32_t displayID; + MMSize size; +}; + +typedef struct _MMDisplaySize MMDisplaySize; + H_INLINE MMPoint MMPointMake(size_t x, size_t y) { MMPoint point; @@ -54,6 +62,15 @@ H_INLINE MMSignedPoint MMSignedPointMake(int32_t x, int32_t y) return point; } +H_INLINE MMDisplaySize MMDisplaySizeMake(int32_t displayID, size_t width, size_t height) +{ + MMDisplaySize diplaySize; + diplaySize.displayID = displayID; + diplaySize.size.width = width; + diplaySize.size.height = height; + return diplaySize; +} + H_INLINE MMSize MMSizeMake(size_t width, size_t height) { MMSize size; @@ -62,10 +79,10 @@ H_INLINE MMSize MMSizeMake(size_t width, size_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; } diff --git a/test/screen.js b/test/screen.js index c16e33b6..b2a43a30 100644 --- a/test/screen.js +++ b/test/screen.js @@ -36,4 +36,10 @@ describe('Screen', () => { expect(screenSize.width !== undefined).toBeTruthy(); expect(screenSize.height !== undefined).toBeTruthy(); }); + it("Get all screens size.", function () { + expect((screenSize = robot.getAllScreensSize())).toBeTruthy(); + expect(screenSize.length).toBeGreaterThan(0); + expect(screenSize[0].width !== undefined).toBeTruthy(); + expect(screenSize[0].height !== undefined).toBeTruthy(); + }); });