Skip to content

Commit 8cb04e5

Browse files
committed
Added keyTap and typeString, started on bitmap.
1 parent 0361eb4 commit 8cb04e5

7 files changed

+166
-31
lines changed

binding.gyp

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,21 @@
77
'include_dirs': [
88
'System/Library/Frameworks/CoreFoundation.Framework/Headers',
99
'System/Library/Frameworks/Carbon.Framework/Headers',
10+
'System/Library/Frameworks/ApplicationServices.framework/Headers',
11+
'System/Library/Frameworks/OpenGL.framework/Headers',
1012
],
1113
"link_settings": {
1214
"libraries": [
1315
"-framework Carbon",
14-
"-framework CoreFoundation"
16+
"-framework CoreFoundation",
17+
"-framework ApplicationServices",
18+
"-framework OpenGL"
1519
]
1620
}
1721
}
1822
]
1923
],
20-
"sources": ["src/robotjs.cc", "src/deadbeef_rand.c", "src/mouse.c", "src/screen.c"]
24+
"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"]
2125
}
2226
]
2327
}

src/keycode.h

+9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
#include <Carbon/Carbon.h> /* Really only need <HIToolbox/Events.h> */
1010
#include <ApplicationServices/ApplicationServices.h>
1111

12+
#ifdef __cplusplus
13+
extern "C"
14+
{
15+
#endif
16+
1217
enum _MMKeyCode {
1318
K_BACKSPACE = kVK_Delete,
1419
K_DELETE = kVK_ForwardDelete,
@@ -124,3 +129,7 @@ typedef int MMKeyCode;
124129
MMKeyCode keyCodeForChar(const char c);
125130

126131
#endif /* KEYCODE_H */
132+
133+
#ifdef __cplusplus
134+
}
135+
#endif

src/keypress.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
#else
1111
#include <stdbool.h>
1212
#endif
13-
13+
#ifdef __cplusplus
14+
extern "C"
15+
{
16+
#endif
1417
#if defined(IS_MACOSX)
1518

1619
enum _MMKeyFlags {
@@ -72,4 +75,8 @@ void typeString(const char *str);
7275
* randomness. */
7376
void typeStringDelayed(const char *str, const unsigned cpm);
7477

78+
#ifdef __cplusplus
79+
}
80+
#endif
81+
7582
#endif /* KEYPRESS_H */

src/robotjs.cc

+89
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,19 @@
33
#include "mouse.h"
44
#include "deadbeef_rand.h"
55
#include "screen.h"
6+
#include "screengrab.h"
7+
#include "keypress.h"
68

79
using namespace v8;
810

11+
/*
12+
__ __
13+
| \/ | ___ _ _ ___ ___
14+
| |\/| |/ _ \| | | / __|/ _ \
15+
| | | | (_) | |_| \__ \ __/
16+
|_| |_|\___/ \__,_|___/\___|
17+
*/
18+
919
Handle<Value> moveMouse(const Arguments& args)
1020
{
1121
HandleScope scope;
@@ -46,6 +56,75 @@ Handle<Value> mouseClick(const Arguments& args)
4656
return scope.Close(String::New("1"));
4757
}
4858

59+
/*
60+
_ __ _ _
61+
| |/ /___ _ _| |__ ___ __ _ _ __ __| |
62+
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
63+
| . \ __/ |_| | |_) | (_) | (_| | | | (_| |
64+
|_|\_\___|\__, |_.__/ \___/ \__,_|_| \__,_|
65+
|___/
66+
*/
67+
68+
char *get(v8::Local<v8::Value> value, const char *fallback = "")
69+
{
70+
if (value->IsString())
71+
{
72+
v8::String::AsciiValue string(value);
73+
char *str = (char *) malloc(string.length() + 1);
74+
strcpy(str, *string);
75+
return str;
76+
}
77+
char *str = (char *) malloc(strlen(fallback) + 1);
78+
strcpy(str, fallback);
79+
return str;
80+
}
81+
82+
Handle<Value> keyTap(const Arguments& args)
83+
{
84+
HandleScope scope;
85+
86+
MMKeyFlags flags = MOD_NONE;
87+
88+
char c = get(args[0])[0];
89+
90+
if (strlen(&c)==1)
91+
{
92+
tapKey(c, flags);
93+
}
94+
95+
return scope.Close(String::New("1"));
96+
}
97+
98+
Handle<Value> typeString(const Arguments& args)
99+
{
100+
HandleScope scope;
101+
102+
char *str = get(args[0]);
103+
104+
typeString(str);
105+
106+
return scope.Close(String::New("1"));
107+
}
108+
109+
//Screen
110+
111+
Handle<Value> captureScreen(const Arguments& args)
112+
{
113+
HandleScope scope;
114+
115+
MMRect rect;
116+
MMBitmapRef bitmap = NULL;
117+
MMSize displaySize = getMainDisplaySize();
118+
119+
rect = MMRectMake(0, 0, displaySize.width, displaySize.height);
120+
121+
bitmap = copyMMBitmapFromDisplayInRect(rect);
122+
123+
return scope.Close(External::Wrap(bitmap));
124+
125+
//return scope.Close(String::New("1"));
126+
}
127+
49128
void init(Handle<Object> target)
50129
{
51130
target->Set(String::NewSymbol("moveMouse"),
@@ -56,5 +135,15 @@ void init(Handle<Object> target)
56135

57136
target->Set(String::NewSymbol("mouseClick"),
58137
FunctionTemplate::New(mouseClick)->GetFunction());
138+
139+
target->Set(String::NewSymbol("keyTap"),
140+
FunctionTemplate::New(keyTap)->GetFunction());
141+
142+
target->Set(String::NewSymbol("typeString"),
143+
FunctionTemplate::New(typeString)->GetFunction());
144+
145+
target->Set(String::NewSymbol("captureScreen"),
146+
FunctionTemplate::New(captureScreen)->GetFunction());
59147
}
148+
60149
NODE_MODULE(robotjs, init)

src/screen.h

+9
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,20 @@
1010
#include <stdbool.h>
1111
#endif
1212

13+
#ifdef __cplusplus
14+
extern "C"
15+
{
16+
#endif
17+
1318
/* Returns the size of the main display. */
1419
MMSize getMainDisplaySize(void);
1520

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

25+
#ifdef __cplusplus
26+
}
27+
#endif
28+
2029
#endif /* SCREEN_H */

src/screengrab.c

+36-28
Original file line numberDiff line numberDiff line change
@@ -32,44 +32,51 @@ static uint8_t *createBufferFromCurrentCGLContext(GLint x,
3232
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect)
3333
{
3434
#if defined(IS_MACOSX)
35-
/* The following is a very modified version of the glGrab code example
36-
* given by Apple (as are some of the convenience functions called). */
35+
3736
size_t bytewidth;
3837
uint8_t bitsPerPixel, bytesPerPixel;
3938
uint8_t *buffer;
4039

41-
/* Build OpenGL context of entire screen */
4240
CGDirectDisplayID displayID = CGMainDisplayID();
43-
CGOpenGLDisplayMask mask = CGDisplayIDToOpenGLDisplayMask(displayID);
44-
CGLContextObj glContext = createFullScreenCGLContext(mask);
45-
if (glContext == NULL) return NULL;
4641

47-
/* TODO: CGDisplayBitsPerPixel() is deprecated in Snow Leopard; I'm not
48-
* sure of the replacement function. */
49-
bitsPerPixel = (uint8_t)CGDisplayBitsPerPixel(displayID);
42+
//Replacement for CGDisplayBitsPerPixel.
43+
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayID);
44+
size_t depth = 0;
45+
46+
CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode);
47+
if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
48+
depth = 32;
49+
else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
50+
depth = 16;
51+
else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
52+
depth = 8;
53+
54+
bitsPerPixel = (uint8_t) depth;
5055
bytesPerPixel = bitsPerPixel / 8;
51-
5256
/* Align width to padding. */
53-
bytewidth = ADD_PADDING(rect.size.width * bytesPerPixel);
57+
//bytewidth = ADD_PADDING(rect.size.width * bytesPerPixel);
58+
bytewidth = rect.size.width * bytesPerPixel;
5459

5560
/* Convert Quartz point to postscript point. */
56-
rect.origin.y = CGDisplayPixelsHigh(displayID) - rect.origin.y - rect.size.height;
57-
58-
/* Extract buffer from context */
59-
buffer = createBufferFromCurrentCGLContext((GLint)rect.origin.x,
60-
(GLint)rect.origin.y,
61-
(GLsizei)rect.size.width,
62-
(GLsizei)rect.size.height,
63-
bytewidth);
64-
/* Reset and release GL context */
65-
destroyFullScreenCGLContext(glContext);
66-
if (buffer == NULL) return NULL;
67-
68-
/* Convert from OpenGL (origin at bottom left) to Quartz (origin at top
69-
* left) coordinate system. */
70-
flipBitmapData(buffer, rect.size.width, rect.size.height, bytewidth);
71-
72-
return createMMBitmap(buffer, rect.size.width, rect.size.height, bytewidth,
61+
//rect.origin.y = CGDisplayPixelsHigh(displayID) - rect.origin.y - rect.size.height;
62+
63+
CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));
64+
65+
// Request access to the raw pixel data via the image's DataProvider.
66+
CGDataProviderRef provider = CGImageGetDataProvider(image);
67+
CFDataRef data = CGDataProviderCopyData(provider);
68+
69+
size_t width, height;
70+
width = CGImageGetWidth(image);
71+
height = CGImageGetHeight(image);
72+
size_t bpp = CGImageGetBitsPerPixel(image) / 8;
73+
74+
uint8 *pixels = malloc(width * height * bpp);
75+
memcpy(pixels, CFDataGetBytePtr(data), width * height * bpp);
76+
CFRelease(data);
77+
CGImageRelease(image);
78+
79+
return createMMBitmap(pixels, rect.size.width, rect.size.height, bytewidth,
7380
bitsPerPixel, bytesPerPixel);
7481
#elif defined(USE_X11)
7582
MMBitmapRef bitmap;
@@ -190,6 +197,7 @@ static CGLContextObj createFullScreenCGLContext(CGOpenGLDisplayMask displayMask)
190197

191198
/* Set full-screen mode. */
192199
CGLSetFullScreen(glContext);
200+
//CGLSetFullScreenOnDisplay(glContext, displayMask);
193201

194202
/* Select front buffer as our source for pixel data. */
195203
glReadBuffer(GL_FRONT);

src/screengrab.h

+9
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,17 @@
55
#include "types.h"
66
#include "MMBitmap.h"
77

8+
#ifdef __cplusplus
9+
extern "C"
10+
{
11+
#endif
12+
813
/* Returns a raw bitmap of screengrab of the display (to be destroyed()'d by
914
* caller), or NULL on error. */
1015
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect);
1116

17+
#ifdef __cplusplus
18+
}
19+
#endif
20+
1221
#endif /* SCREENGRAB_H */

0 commit comments

Comments
 (0)