Skip to content

Commit

Permalink
Added keyTap and typeString, started on bitmap.
Browse files Browse the repository at this point in the history
  • Loading branch information
octalmage committed Sep 6, 2014
1 parent 0361eb4 commit 8cb04e5
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 31 deletions.
8 changes: 6 additions & 2 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@
'include_dirs': [
'System/Library/Frameworks/CoreFoundation.Framework/Headers',
'System/Library/Frameworks/Carbon.Framework/Headers',
'System/Library/Frameworks/ApplicationServices.framework/Headers',
'System/Library/Frameworks/OpenGL.framework/Headers',
],
"link_settings": {
"libraries": [
"-framework Carbon",
"-framework CoreFoundation"
"-framework CoreFoundation",
"-framework ApplicationServices",
"-framework OpenGL"
]
}
}
]
],
"sources": ["src/robotjs.cc", "src/deadbeef_rand.c", "src/mouse.c", "src/screen.c"]
"sources": ["src/robotjs.cc", "src/deadbeef_rand.c", "src/mouse.c", "src/screen.c", "src/keypress.c" , "src/keycode.c", "src/screengrab.c", "src/MMBitmap.c"]
}
]
}
9 changes: 9 additions & 0 deletions src/keycode.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
#include <Carbon/Carbon.h> /* Really only need <HIToolbox/Events.h> */
#include <ApplicationServices/ApplicationServices.h>

#ifdef __cplusplus
extern "C"
{
#endif

enum _MMKeyCode {
K_BACKSPACE = kVK_Delete,
K_DELETE = kVK_ForwardDelete,
Expand Down Expand Up @@ -124,3 +129,7 @@ typedef int MMKeyCode;
MMKeyCode keyCodeForChar(const char c);

#endif /* KEYCODE_H */

#ifdef __cplusplus
}
#endif
9 changes: 8 additions & 1 deletion src/keypress.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
#else
#include <stdbool.h>
#endif

#ifdef __cplusplus
extern "C"
{
#endif
#if defined(IS_MACOSX)

enum _MMKeyFlags {
Expand Down Expand Up @@ -72,4 +75,8 @@ void typeString(const char *str);
* randomness. */
void typeStringDelayed(const char *str, const unsigned cpm);

#ifdef __cplusplus
}
#endif

#endif /* KEYPRESS_H */
89 changes: 89 additions & 0 deletions src/robotjs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,19 @@
#include "mouse.h"
#include "deadbeef_rand.h"
#include "screen.h"
#include "screengrab.h"
#include "keypress.h"

using namespace v8;

/*
__ __
| \/ | ___ _ _ ___ ___
| |\/| |/ _ \| | | / __|/ _ \
| | | | (_) | |_| \__ \ __/
|_| |_|\___/ \__,_|___/\___|
*/

Handle<Value> moveMouse(const Arguments& args)
{
HandleScope scope;
Expand Down Expand Up @@ -46,6 +56,75 @@ Handle<Value> mouseClick(const Arguments& args)
return scope.Close(String::New("1"));
}

/*
_ __ _ _
| |/ /___ _ _| |__ ___ __ _ _ __ __| |
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
| . \ __/ |_| | |_) | (_) | (_| | | | (_| |
|_|\_\___|\__, |_.__/ \___/ \__,_|_| \__,_|
|___/
*/

char *get(v8::Local<v8::Value> value, const char *fallback = "")
{
if (value->IsString())
{
v8::String::AsciiValue string(value);
char *str = (char *) malloc(string.length() + 1);
strcpy(str, *string);
return str;
}
char *str = (char *) malloc(strlen(fallback) + 1);
strcpy(str, fallback);
return str;
}

Handle<Value> keyTap(const Arguments& args)
{
HandleScope scope;

MMKeyFlags flags = MOD_NONE;

char c = get(args[0])[0];

if (strlen(&c)==1)
{
tapKey(c, flags);
}

return scope.Close(String::New("1"));
}

Handle<Value> typeString(const Arguments& args)
{
HandleScope scope;

char *str = get(args[0]);

typeString(str);

return scope.Close(String::New("1"));
}

//Screen

Handle<Value> captureScreen(const Arguments& args)
{
HandleScope scope;

MMRect rect;
MMBitmapRef bitmap = NULL;
MMSize displaySize = getMainDisplaySize();

rect = MMRectMake(0, 0, displaySize.width, displaySize.height);

bitmap = copyMMBitmapFromDisplayInRect(rect);

return scope.Close(External::Wrap(bitmap));

//return scope.Close(String::New("1"));
}

void init(Handle<Object> target)
{
target->Set(String::NewSymbol("moveMouse"),
Expand All @@ -56,5 +135,15 @@ void init(Handle<Object> target)

target->Set(String::NewSymbol("mouseClick"),
FunctionTemplate::New(mouseClick)->GetFunction());

target->Set(String::NewSymbol("keyTap"),
FunctionTemplate::New(keyTap)->GetFunction());

target->Set(String::NewSymbol("typeString"),
FunctionTemplate::New(typeString)->GetFunction());

target->Set(String::NewSymbol("captureScreen"),
FunctionTemplate::New(captureScreen)->GetFunction());
}

NODE_MODULE(robotjs, init)
9 changes: 9 additions & 0 deletions src/screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,20 @@
#include <stdbool.h>
#endif

#ifdef __cplusplus
extern "C"
{
#endif

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

/* Convenience function that returns whether the given point is in the bounds
* of the main screen. */
bool pointVisibleOnMainDisplay(MMPoint point);

#ifdef __cplusplus
}
#endif

#endif /* SCREEN_H */
64 changes: 36 additions & 28 deletions src/screengrab.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,44 +32,51 @@ static uint8_t *createBufferFromCurrentCGLContext(GLint x,
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect)
{
#if defined(IS_MACOSX)
/* The following is a very modified version of the glGrab code example
* given by Apple (as are some of the convenience functions called). */

size_t bytewidth;
uint8_t bitsPerPixel, bytesPerPixel;
uint8_t *buffer;

/* Build OpenGL context of entire screen */
CGDirectDisplayID displayID = CGMainDisplayID();
CGOpenGLDisplayMask mask = CGDisplayIDToOpenGLDisplayMask(displayID);
CGLContextObj glContext = createFullScreenCGLContext(mask);
if (glContext == NULL) return NULL;

/* TODO: CGDisplayBitsPerPixel() is deprecated in Snow Leopard; I'm not
* sure of the replacement function. */
bitsPerPixel = (uint8_t)CGDisplayBitsPerPixel(displayID);
//Replacement for CGDisplayBitsPerPixel.
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayID);
size_t depth = 0;

CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode);
if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
depth = 32;
else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
depth = 16;
else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
depth = 8;

bitsPerPixel = (uint8_t) depth;
bytesPerPixel = bitsPerPixel / 8;

/* Align width to padding. */
bytewidth = ADD_PADDING(rect.size.width * bytesPerPixel);
//bytewidth = ADD_PADDING(rect.size.width * bytesPerPixel);
bytewidth = rect.size.width * bytesPerPixel;

/* Convert Quartz point to postscript point. */
rect.origin.y = CGDisplayPixelsHigh(displayID) - rect.origin.y - rect.size.height;

/* Extract buffer from context */
buffer = createBufferFromCurrentCGLContext((GLint)rect.origin.x,
(GLint)rect.origin.y,
(GLsizei)rect.size.width,
(GLsizei)rect.size.height,
bytewidth);
/* Reset and release GL context */
destroyFullScreenCGLContext(glContext);
if (buffer == NULL) return NULL;

/* Convert from OpenGL (origin at bottom left) to Quartz (origin at top
* left) coordinate system. */
flipBitmapData(buffer, rect.size.width, rect.size.height, bytewidth);

return createMMBitmap(buffer, rect.size.width, rect.size.height, bytewidth,
//rect.origin.y = CGDisplayPixelsHigh(displayID) - rect.origin.y - rect.size.height;

CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));

// Request access to the raw pixel data via the image's DataProvider.
CGDataProviderRef provider = CGImageGetDataProvider(image);
CFDataRef data = CGDataProviderCopyData(provider);

size_t width, height;
width = CGImageGetWidth(image);
height = CGImageGetHeight(image);
size_t bpp = CGImageGetBitsPerPixel(image) / 8;

uint8 *pixels = malloc(width * height * bpp);
memcpy(pixels, CFDataGetBytePtr(data), width * height * bpp);
CFRelease(data);
CGImageRelease(image);

return createMMBitmap(pixels, rect.size.width, rect.size.height, bytewidth,
bitsPerPixel, bytesPerPixel);
#elif defined(USE_X11)
MMBitmapRef bitmap;
Expand Down Expand Up @@ -190,6 +197,7 @@ static CGLContextObj createFullScreenCGLContext(CGOpenGLDisplayMask displayMask)

/* Set full-screen mode. */
CGLSetFullScreen(glContext);
//CGLSetFullScreenOnDisplay(glContext, displayMask);

/* Select front buffer as our source for pixel data. */
glReadBuffer(GL_FRONT);
Expand Down
9 changes: 9 additions & 0 deletions src/screengrab.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,17 @@
#include "types.h"
#include "MMBitmap.h"

#ifdef __cplusplus
extern "C"
{
#endif

/* Returns a raw bitmap of screengrab of the display (to be destroyed()'d by
* caller), or NULL on error. */
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect);

#ifdef __cplusplus
}
#endif

#endif /* SCREENGRAB_H */

0 comments on commit 8cb04e5

Please # to comment.