forked from mpereiraesaa/libnut
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmouse.c
178 lines (149 loc) · 5.86 KB
/
mouse.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include "../mouse.h"
#include "../microsleep.h"
#include <math.h> /* For floor() */
#include <ApplicationServices/ApplicationServices.h>
#if !defined(M_SQRT2)
#define M_SQRT2 1.4142135623730950488016887 /* Fix for MSVC. */
#endif
#define MMMouseToCGEventType(down, button) \
(down ? MMMouseDownToCGEventType(button) : MMMouseUpToCGEventType(button))
#define MMMouseDownToCGEventType(button) \
((button) == (LEFT_BUTTON) ? kCGEventLeftMouseDown \
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseDown \
: kCGEventOtherMouseDown))
#define MMMouseUpToCGEventType(button) \
((button) == LEFT_BUTTON ? kCGEventLeftMouseUp \
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseUp \
: kCGEventOtherMouseUp))
#define MMMouseDragToCGEventType(button) \
((button) == LEFT_BUTTON ? kCGEventLeftMouseDragged \
: ((button) == RIGHT_BUTTON ? kCGEventRightMouseDragged \
: kCGEventOtherMouseDragged))
/**
* Calculate the delta for a mouse move and add them to the event.
* @param event The mouse move event (by ref).
* @param point The new mouse x and y.
*/
void calculateDeltas(CGEventRef *event, MMPoint point)
{
/**
* The next few lines are a workaround for games not detecting mouse moves.
* See this issue for more information:
* https://github.com/octalmage/robotjs/issues/159
*/
CGEventRef get = CGEventCreate(NULL);
CGPoint mouse = CGEventGetLocation(get);
// Calculate the deltas.
int64_t deltaX = point.x - mouse.x;
int64_t deltaY = point.y - mouse.y;
CGEventSetIntegerValueField(*event, kCGMouseEventDeltaX, deltaX);
CGEventSetIntegerValueField(*event, kCGMouseEventDeltaY, deltaY);
CFRelease(get);
}
/**
* Move the mouse to a specific point.
* @param point The coordinates to move the mouse to (x, y).
*/
void moveMouse(MMPoint point)
{
CGPoint position = CGPointMake(point.x, point.y);
// Create an HID hardware event source
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef evt = NULL;
if (CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonLeft))
{
// Create a left button drag
evt = CGEventCreateMouseEvent(src, kCGEventLeftMouseDragged, position, kCGMouseButtonLeft);
}
else
{
if (CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonRight))
{
// Create a right button drag
evt = CGEventCreateMouseEvent(src, kCGEventRightMouseDragged, position, kCGMouseButtonLeft);
}
else
{
// Create a mouse move event
evt = CGEventCreateMouseEvent(src, kCGEventMouseMoved, position, kCGMouseButtonLeft);
}
}
// Post mouse event and release
CGEventPost(kCGHIDEventTap, evt);
if (evt != NULL)
{
CFRelease(evt);
}
CFRelease(src);
}
void dragMouse(MMPoint point, const MMMouseButton button)
{
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
const CGEventType dragType = MMMouseDragToCGEventType(button);
CGEventRef drag = CGEventCreateMouseEvent(src, dragType, CGPointFromMMPoint(point), (CGMouseButton)button);
calculateDeltas(&drag, point);
CGEventPost(kCGHIDEventTap, drag);
CFRelease(drag);
CFRelease(src);
}
MMPoint getMousePos()
{
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef event = CGEventCreate(src);
CGPoint point = CGEventGetLocation(event);
CFRelease(event);
CFRelease(src);
return MMSignedPointFromCGPoint(point);
}
/**
* Press down a button, or release it.
* @param down True for down, false for up.
* @param button The button to press down or release.
*/
void toggleMouse(bool down, MMMouseButton button)
{
const CGPoint currentPos = CGPointFromMMSignedPoint(getMousePos());
const CGEventType mouseType = MMMouseToCGEventType(down, button);
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef event = CGEventCreateMouseEvent(src, mouseType, currentPos, (CGMouseButton)button);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
CFRelease(src);
}
void clickMouse(MMMouseButton button)
{
toggleMouse(true, button);
toggleMouse(false, button);
}
/**
* Special function for sending double clicks, needed for Mac OS X.
* @param button Button to click.
*/
void doubleClick(MMMouseButton button)
{
/* Double click for Mac. */
const CGPoint currentPos = CGPointFromMMPoint(getMousePos());
const CGEventType mouseTypeDown = MMMouseToCGEventType(true, button);
const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button);
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef event = CGEventCreateMouseEvent(src, mouseTypeDown, currentPos, kCGMouseButtonLeft);
/* Set event to double click. */
CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2);
CGEventPost(kCGHIDEventTap, event);
CGEventSetType(event, mouseTypeUP);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
CFRelease(src);
}
void scrollMouse(int x, int y)
{
/*
* Direction should only be considered based on the scrollDirection.
* This should not interfere.
* Set up the OS specific solution
*/
CGEventRef event;
event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, y, x);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}