23 #if SDL_VIDEO_DRIVER_COCOA
32 #if SDL_MAC_NO_SANDBOX
35 #include "SDL_thread.h"
38 #include "../../events/SDL_mouse_c.h"
43 CFRunLoopSourceRef runloopSource;
45 SDL_sem *runloopStartedSemaphore;
46 } SDL_MouseEventTapData;
48 static const CGEventMask movementEventsMask =
49 CGEventMaskBit(kCGEventLeftMouseDragged)
50 | CGEventMaskBit(kCGEventRightMouseDragged)
51 | CGEventMaskBit(kCGEventMouseMoved);
53 static const CGEventMask allGrabbedEventsMask =
54 CGEventMaskBit(kCGEventLeftMouseDown) | CGEventMaskBit(kCGEventLeftMouseUp)
55 | CGEventMaskBit(kCGEventRightMouseDown) | CGEventMaskBit(kCGEventRightMouseUp)
56 | CGEventMaskBit(kCGEventOtherMouseDown) | CGEventMaskBit(kCGEventOtherMouseUp)
57 | CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged)
58 | CGEventMaskBit(kCGEventMouseMoved);
61 Cocoa_MouseTapCallback(CGEventTapProxy proxy, CGEventType
type, CGEventRef
event,
void *refcon)
67 CGPoint eventLocation;
71 case kCGEventTapDisabledByTimeout:
72 case kCGEventTapDisabledByUserInput:
74 CGEventTapEnable(((SDL_MouseEventTapData*)(driverdata->
tapdata))->tap,
true);
82 if (!window || !mouse) {
95 eventLocation = CGEventGetUnflippedLocation(event);
98 if (!NSPointInRect(NSPointFromCGPoint(eventLocation), windowRect)) {
103 CGPoint newLocation = CGEventGetLocation(event);
105 if (eventLocation.x < NSMinX(windowRect)) {
106 newLocation.x = NSMinX(windowRect);
107 }
else if (eventLocation.x >= NSMaxX(windowRect)) {
108 newLocation.x = NSMaxX(windowRect) - 1.0;
111 if (eventLocation.y < NSMinY(windowRect)) {
112 newLocation.y -= (NSMinY(windowRect) - eventLocation.
y + 1);
113 }
else if (eventLocation.y >= NSMaxY(windowRect)) {
114 newLocation.y += (eventLocation.
y - NSMaxY(windowRect) + 1);
117 CGSetLocalEventsSuppressionInterval(0);
118 CGWarpMouseCursorPosition(newLocation);
119 CGSetLocalEventsSuppressionInterval(0.25);
121 if ((CGEventMaskBit(type) & movementEventsMask) == 0) {
127 CGEventSetLocation(event, newLocation);
135 SemaphorePostCallback(CFRunLoopTimerRef timer,
void *info)
141 Cocoa_MouseTapThread(
void *
data)
143 SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)data;
146 CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
147 kCGEventTapOptionDefault, allGrabbedEventsMask,
148 &Cocoa_MouseTapCallback, tapdata);
151 CFRunLoopSourceRef runloopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
153 tapdata->tap = eventTap;
154 tapdata->runloopSource = runloopSource;
170 tapdata->runloop = CFRunLoopGetCurrent();
171 CFRunLoopAddSource(tapdata->runloop, tapdata->runloopSource, kCFRunLoopCommonModes);
172 CFRunLoopTimerContext
context = {.info = tapdata->runloopStartedSemaphore};
174 CFRunLoopTimerRef timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 0, 0, 0, &SemaphorePostCallback, &context);
175 CFRunLoopAddTimer(tapdata->runloop, timer, kCFRunLoopCommonModes);
181 if (
SDL_SemValue(tapdata->runloopStartedSemaphore) < 1) {
184 CFRunLoopRemoveSource(tapdata->runloop, tapdata->runloopSource, kCFRunLoopCommonModes);
187 CGEventTapEnable(tapdata->tap,
false);
188 CFRelease(tapdata->runloopSource);
189 CFRelease(tapdata->tap);
190 tapdata->runloopSource =
NULL;
199 SDL_MouseEventTapData *tapdata;
201 tapdata = (SDL_MouseEventTapData*)driverdata->
tapdata;
204 if (tapdata->runloopStartedSemaphore) {
205 tapdata->thread =
SDL_CreateThread(&Cocoa_MouseTapThread,
"Event Tap Loop", tapdata);
206 if (!tapdata->thread) {
211 if (!tapdata->thread) {
220 SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->
tapdata;
231 CFRunLoopStop(tapdata->runloop);
DECLSPEC SDL_sem *SDLCALL SDL_CreateSemaphore(Uint32 initial_value)
SDL_Mouse * SDL_GetMouse(void)
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size)
struct SDL_semaphore SDL_sem
DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 ms)
DECLSPEC void SDLCALL SDL_free(void *mem)
DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread *thread, int *status)
void Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem)
DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem)
DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data)
static SDL_Thread * thread
EGLSurface EGLint EGLint y
DECLSPEC SDL_Window *SDLCALL SDL_GetKeyboardFocus(void)
Get the window which currently has keyboard focus.
DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem)
void Cocoa_InitMouseEventTap(SDL_MouseData *driverdata)