Skip to content

Commit

Permalink
Add initial support for multi-display
Browse files Browse the repository at this point in the history
  • Loading branch information
vinvol committed May 26, 2020
1 parent c9cbd98 commit b80b20c
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 13 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
47 changes: 41 additions & 6 deletions src/robotjs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -689,15 +689,22 @@ NAN_METHOD(getPixelColor)
MMBitmapRef bitmap;
MMRGBHex color;

size_t x = Nan::To<int32_t>(info[0]).FromJust();
size_t y = Nan::To<int32_t>(info[1]).FromJust();
float x = Nan::To<int32_t>(info[0]).FromJust();
float y = Nan::To<int32_t>(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);

Expand All @@ -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<Array> list = Nan::New<Array>(numDisplays);
for (uint32_t i = 0; i < numDisplays; i++)
{
Local<Object> obj = Nan::New<Object>();
Nan::Set(obj, Nan::New("displayID").ToLocalChecked(), Nan::New<Number>(displaySizes[i].displayID));
Nan::Set(obj, Nan::New("width").ToLocalChecked(), Nan::New<Number>(displaySizes[i].size.width));
Nan::Set(obj, Nan::New("height").ToLocalChecked(), Nan::New<Number>(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)
Expand Down Expand Up @@ -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<Object> buffer = Nan::NewBuffer((char*)bitmap->imageBuffer, bufferSize, destroyMMBitmapBuffer, NULL).ToLocalChecked();
Expand Down Expand Up @@ -918,6 +950,9 @@ NAN_MODULE_INIT(InitAll)
Nan::Set(target, Nan::New("getScreenSize").ToLocalChecked(),
Nan::GetFunction(Nan::New<FunctionTemplate>(getScreenSize)).ToLocalChecked());

Nan::Set(target, Nan::New("getAllScreensSize").ToLocalChecked(),
Nan::GetFunction(Nan::New<FunctionTemplate>(getAllScreensSize)).ToLocalChecked());

Nan::Set(target, Nan::New("captureScreen").ToLocalChecked(),
Nan::GetFunction(Nan::New<FunctionTemplate>(captureScreen)).ToLocalChecked());

Expand Down
18 changes: 18 additions & 0 deletions src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions src/screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 1 addition & 3 deletions src/screengrab.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,14 @@
#include <string.h>
#endif

MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect)
MMBitmapRef copyMMBitmapFromDisplayInRect(int32_t displayID, MMRect rect)
{
#if defined(IS_MACOSX)

MMBitmapRef bitmap = NULL;
uint8_t *buffer = NULL;
size_t bufferSize = 0;

CGDirectDisplayID displayID = CGMainDisplayID();

CGImageRef image = CGDisplayCreateImageForRect(displayID,
CGRectMake(rect.origin.x,
rect.origin.y,
Expand Down
2 changes: 1 addition & 1 deletion src/screengrab.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
23 changes: 20 additions & 3 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions test/screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
});

0 comments on commit b80b20c

Please sign in to comment.