From 354a8f276e25f9182f758fd3cf672064bc12b9bc Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 26 Nov 2016 10:26:22 -0800 Subject: [PATCH] SDL for Mac - only enable global event tap when actually necessary (app has focus and has requested relative mouse mode or has asked for a mouse grab). in other situations the event tap impacts system performance and battery life with no benefit. --- src/video/cocoa/SDL_cocoamousetap.h | 1 + src/video/cocoa/SDL_cocoamousetap.m | 39 +++++++++++++++++++++-------- src/video/cocoa/SDL_cocoawindow.m | 8 +++++- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/video/cocoa/SDL_cocoamousetap.h b/src/video/cocoa/SDL_cocoamousetap.h index af92314b6..795248a23 100644 --- a/src/video/cocoa/SDL_cocoamousetap.h +++ b/src/video/cocoa/SDL_cocoamousetap.h @@ -26,6 +26,7 @@ #include "SDL_cocoamouse.h" extern void Cocoa_InitMouseEventTap(SDL_MouseData *driverdata); +extern void Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled); extern void Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata); #endif /* _SDL_cocoamousetap_h */ diff --git a/src/video/cocoa/SDL_cocoamousetap.m b/src/video/cocoa/SDL_cocoamousetap.m index 48abbca9c..a36e42307 100644 --- a/src/video/cocoa/SDL_cocoamousetap.m +++ b/src/video/cocoa/SDL_cocoamousetap.m @@ -142,15 +142,12 @@ Cocoa_MouseTapThread(void *data) { SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)data; - /* Create a tap. */ - CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, - kCGEventTapOptionDefault, allGrabbedEventsMask, - &Cocoa_MouseTapCallback, tapdata); + /* Tap was created on main thread but we own it now. */ + CFMachPortRef eventTap = tapdata->tap; if (eventTap) { /* Try to create a runloop source we can schedule. */ CFRunLoopSourceRef runloopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0); if (runloopSource) { - tapdata->tap = eventTap; tapdata->runloopSource = runloopSource; } else { CFRelease(eventTap); @@ -202,15 +199,30 @@ Cocoa_InitMouseEventTap(SDL_MouseData* driverdata) tapdata->runloopStartedSemaphore = SDL_CreateSemaphore(0); if (tapdata->runloopStartedSemaphore) { - tapdata->thread = SDL_CreateThreadInternal(&Cocoa_MouseTapThread, "Event Tap Loop", 512 * 1024, tapdata); - if (!tapdata->thread) { - SDL_DestroySemaphore(tapdata->runloopStartedSemaphore); + tapdata->tap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, + kCGEventTapOptionDefault, allGrabbedEventsMask, + &Cocoa_MouseTapCallback, tapdata); + if (tapdata->tap) { + tapdata->thread = SDL_CreateThreadInternal(&Cocoa_MouseTapThread, "Event Tap Loop", 512 * 1024, tapdata); + if (tapdata->thread) { + /* Success - early out. Ownership transferred to thread. */ + return; + } + CFRelease(tapdata->tap); } + SDL_DestroySemaphore(tapdata->runloopStartedSemaphore); } + SDL_free(driverdata->tapdata); + driverdata->tapdata = NULL; +} - if (!tapdata->thread) { - SDL_free(driverdata->tapdata); - driverdata->tapdata = NULL; +void +Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled) +{ + SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->tapdata; + if (tapdata && tapdata->tap) + { + CGEventTapEnable(tapdata->tap, enabled); } } @@ -245,6 +257,11 @@ Cocoa_InitMouseEventTap(SDL_MouseData *unused) { } +void +Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled) +{ +} + void Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata) { diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index cfad54854..f705a6c47 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -38,6 +38,7 @@ #include "SDL_cocoavideo.h" #include "SDL_cocoashape.h" #include "SDL_cocoamouse.h" +#include "SDL_cocoamousetap.h" #include "SDL_cocoaopengl.h" #include "SDL_assert.h" @@ -1634,8 +1635,13 @@ Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp) void Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed) { - /* Move the cursor to the nearest point in the window */ + SDL_Mouse *mouse = SDL_GetMouse(); SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + + /* Enable or disable the event tap as necessary */ + Cocoa_EnableMouseEventTap(mouse->driverdata, grabbed); + + /* Move the cursor to the nearest point in the window */ if (grabbed && data && ![data->listener isMoving]) { int x, y; CGPoint cgpoint;