Skip to content

Commit 406acfb

Browse files
committed
Added dragMouse function
Fixes #127
1 parent 9edeefc commit 406acfb

File tree

3 files changed

+136
-68
lines changed

3 files changed

+136
-68
lines changed

src/mouse.c

+52-33
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,44 @@
1818
#define M_SQRT2 1.4142135623730950488016887 /* Fix for MSVC. */
1919
#endif
2020

21+
/* Some convenience macros for converting our enums to the system API types. */
22+
#if defined(IS_MACOSX)
23+
24+
#define MMMouseToCGEventType(down, button) \
25+
(down ? MMMouseDownToCGEventType(button) : MMMouseUpToCGEventType(button))
26+
27+
#define MMMouseDownToCGEventType(button) \
28+
((button) == (LEFT_BUTTON) ? kCGEventLeftMouseDown \
29+
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseDown \
30+
: kCGEventOtherMouseDown))
31+
32+
#define MMMouseUpToCGEventType(button) \
33+
((button) == LEFT_BUTTON ? kCGEventLeftMouseUp \
34+
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseUp \
35+
: kCGEventOtherMouseUp))
36+
37+
#define MMMouseDragToCGEventType(button) \
38+
((button) == LEFT_BUTTON ? kCGEventLeftMouseDragged \
39+
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseDragged \
40+
: kCGEventOtherMouseDragged))
41+
42+
#elif defined(IS_WINDOWS)
43+
44+
#define MMMouseToMEventF(down, button) \
45+
(down ? MMMouseDownToMEventF(button) : MMMouseUpToMEventF(button))
46+
47+
#define MMMouseUpToMEventF(button) \
48+
((button) == LEFT_BUTTON ? MOUSEEVENTF_LEFTUP \
49+
: ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTUP \
50+
: MOUSEEVENTF_MIDDLEUP))
51+
52+
#define MMMouseDownToMEventF(button) \
53+
((button) == LEFT_BUTTON ? MOUSEEVENTF_LEFTDOWN \
54+
: ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTDOWN \
55+
: MOUSEEVENTF_MIDDLEDOWN))
56+
57+
#endif
58+
2159
/**
2260
* Move the mouse to a specific point.
2361
* @param point The coordinates to move the mouse to (x, y).
@@ -44,6 +82,20 @@ void moveMouse(MMPoint point)
4482
#endif
4583
}
4684

85+
void dragMouse(MMPoint point, const MMMouseButton button)
86+
{
87+
#if defined(IS_MACOSX)
88+
const CGEventType dragType = MMMouseDragToCGEventType(button);
89+
const CGEventRef drag = CGEventCreateMouseEvent(NULL, dragType,
90+
CGPointFromMMPoint(point),
91+
(CGMouseButton)button);
92+
CGEventPost(kCGSessionEventTap, drag);
93+
CFRelease(drag);
94+
#else
95+
moveMouse(point);
96+
#endif
97+
}
98+
4799
MMPoint getMousePos()
48100
{
49101
#if defined(IS_MACOSX)
@@ -71,39 +123,6 @@ MMPoint getMousePos()
71123
#endif
72124
}
73125

74-
/* Some convenience macros for converting our enums to the system API types. */
75-
#if defined(IS_MACOSX)
76-
77-
#define MMMouseToCGEventType(down, button) \
78-
(down ? MMMouseDownToCGEventType(button) : MMMouseUpToCGEventType(button))
79-
80-
#define MMMouseDownToCGEventType(button) \
81-
((button) == (LEFT_BUTTON) ? kCGEventLeftMouseDown \
82-
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseDown \
83-
: kCGEventOtherMouseDown))
84-
85-
#define MMMouseUpToCGEventType(button) \
86-
((button) == LEFT_BUTTON ? kCGEventLeftMouseUp \
87-
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseUp \
88-
: kCGEventOtherMouseUp))
89-
90-
#elif defined(IS_WINDOWS)
91-
92-
#define MMMouseToMEventF(down, button) \
93-
(down ? MMMouseDownToMEventF(button) : MMMouseUpToMEventF(button))
94-
95-
#define MMMouseUpToMEventF(button) \
96-
((button) == LEFT_BUTTON ? MOUSEEVENTF_LEFTUP \
97-
: ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTUP \
98-
: MOUSEEVENTF_MIDDLEUP))
99-
100-
#define MMMouseDownToMEventF(button) \
101-
((button) == LEFT_BUTTON ? MOUSEEVENTF_LEFTDOWN \
102-
: ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTDOWN \
103-
: MOUSEEVENTF_MIDDLEDOWN))
104-
105-
#endif
106-
107126
/**
108127
* Press down a button, or release it.
109128
* @param down True for down, false for up.

src/mouse.h

+6
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ typedef int MMMouseWheelDirection;
6262
* screen boundaries. */
6363
void moveMouse(MMPoint point);
6464

65+
/* Like moveMouse, moves the mouse to the given point on-screen, but marks
66+
* the event as the mouse being dragged on platforms where it is supported.
67+
* It is up to the caller to ensure that this point is within the screen
68+
* boundaries. */
69+
void dragMouse(MMPoint point, const MMMouseButton button);
70+
6571
/* Smoothly moves the mouse from the current position to the given point.
6672
* deadbeef_srand() should be called before using this function.
6773
*

src/robotjs.cc

+78-35
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,66 @@ int keyboardDelay = 10;
2626
2727
*/
2828

29-
NAN_METHOD(moveMouse)
29+
int CheckMouseButton(const char * const b, MMMouseButton * const button)
30+
{
31+
if (!button) return -1;
32+
33+
if (strcmp(b, "left") == 0)
34+
{
35+
*button = LEFT_BUTTON;
36+
}
37+
else if (strcmp(b, "right") == 0)
38+
{
39+
*button = RIGHT_BUTTON;
40+
}
41+
else if (strcmp(b, "middle") == 0)
42+
{
43+
*button = CENTER_BUTTON;
44+
}
45+
else
46+
{
47+
return -2;
48+
}
49+
50+
return 0;
51+
}
52+
53+
NAN_METHOD(dragMouse)
54+
{
55+
if (info.Length() < 2)
56+
{
57+
return Nan::ThrowError("Invalid number of arguments.");
58+
}
59+
60+
const size_t x = info[0]->Int32Value();
61+
const size_t y = info[1]->Int32Value();
62+
MMMouseButton button = LEFT_BUTTON;
63+
64+
if (info.Length() >= 3)
65+
{
66+
Nan::Utf8String bstr(info[2]);
67+
const char * const b = *bstr;
68+
69+
switch (CheckMouseButton(b, &button))
70+
{
71+
case -1:
72+
return Nan::ThrowError("Null pointer in mouse button code.");
73+
break;
74+
case -2:
75+
return Nan::ThrowError("Invalid mouse button specified.");
76+
break;
77+
}
78+
}
79+
80+
MMPoint point;
81+
point = MMPointMake(x, y);
82+
dragMouse(point, button);
83+
microsleep(mouseDelay);
84+
85+
info.GetReturnValue().Set(Nan::New(1));
86+
}
87+
88+
NAN_METHOD(moveMouse)
3089
{
3190
if (info.Length() < 2)
3291
{
@@ -78,26 +137,17 @@ NAN_METHOD(mouseClick)
78137

79138
if (info.Length() > 0)
80139
{
81-
char *b;
82-
83140
v8::String::Utf8Value bstr(info[0]->ToString());
84-
b = *bstr;
141+
const char * const b = *bstr;
85142

86-
if (strcmp(b, "left") == 0)
87-
{
88-
button = LEFT_BUTTON;
89-
}
90-
else if (strcmp(b, "right") == 0)
143+
switch (CheckMouseButton(b, &button))
91144
{
92-
button = RIGHT_BUTTON;
93-
}
94-
else if (strcmp(b, "middle") == 0)
95-
{
96-
button = CENTER_BUTTON;
97-
}
98-
else
99-
{
100-
return Nan::ThrowError("Invalid mouse button specified.");
145+
case -1:
146+
return Nan::ThrowError("Null pointer in mouse button code.");
147+
break;
148+
case -2:
149+
return Nan::ThrowError("Invalid mouse button specified.");
150+
break;
101151
}
102152
}
103153

@@ -152,26 +202,17 @@ NAN_METHOD(mouseToggle)
152202

153203
if (info.Length() == 2)
154204
{
155-
char *b;
156-
157205
Nan::Utf8String bstr(info[1]);
158-
b = *bstr;
206+
const char * const b = *bstr;
159207

160-
if (strcmp(b, "left") == 0)
161-
{
162-
button = LEFT_BUTTON;
163-
}
164-
else if (strcmp(b, "right") == 0)
208+
switch (CheckMouseButton(b, &button))
165209
{
166-
button = RIGHT_BUTTON;
167-
}
168-
else if (strcmp(b, "middle") == 0)
169-
{
170-
button = CENTER_BUTTON;
171-
}
172-
else
173-
{
174-
return Nan::ThrowError("Invalid mouse button specified.");
210+
case -1:
211+
return Nan::ThrowError("Null pointer in mouse button code.");
212+
break;
213+
case -2:
214+
return Nan::ThrowError("Invalid mouse button specified.");
215+
break;
175216
}
176217
}
177218
else if (info.Length() > 2)
@@ -628,6 +669,8 @@ NAN_METHOD(getScreenSize)
628669

629670
NAN_MODULE_INIT(InitAll)
630671
{
672+
Nan::Set(target, Nan::New("dragMouse").ToLocalChecked(),
673+
Nan::GetFunction(Nan::New<FunctionTemplate>(dragMouse)).ToLocalChecked());
631674

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

0 commit comments

Comments
 (0)