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.
authorSam Lantinga <slouken@libsdl.org>
Sat, 26 Nov 2016 10:26:22 -0800
changeset 10653f87d76304c76
parent 10652 c3fbfa229d71
child 10654 a9713e5c7788
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
src/video/cocoa/SDL_cocoamousetap.m
src/video/cocoa/SDL_cocoawindow.m
     1.1 --- a/src/video/cocoa/SDL_cocoamousetap.h	Fri Nov 25 14:16:27 2016 -0500
     1.2 +++ b/src/video/cocoa/SDL_cocoamousetap.h	Sat Nov 26 10:26:22 2016 -0800
     1.3 @@ -26,6 +26,7 @@
     1.4  #include "SDL_cocoamouse.h"
     1.5  
     1.6  extern void Cocoa_InitMouseEventTap(SDL_MouseData *driverdata);
     1.7 +extern void Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled);
     1.8  extern void Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata);
     1.9  
    1.10  #endif /* _SDL_cocoamousetap_h */
     2.1 --- a/src/video/cocoa/SDL_cocoamousetap.m	Fri Nov 25 14:16:27 2016 -0500
     2.2 +++ b/src/video/cocoa/SDL_cocoamousetap.m	Sat Nov 26 10:26:22 2016 -0800
     2.3 @@ -142,15 +142,12 @@
     2.4  {
     2.5      SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)data;
     2.6  
     2.7 -    /* Create a tap. */
     2.8 -    CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
     2.9 -                                              kCGEventTapOptionDefault, allGrabbedEventsMask,
    2.10 -                                              &Cocoa_MouseTapCallback, tapdata);
    2.11 +    /* Tap was created on main thread but we own it now. */
    2.12 +    CFMachPortRef eventTap = tapdata->tap;
    2.13      if (eventTap) {
    2.14          /* Try to create a runloop source we can schedule. */
    2.15          CFRunLoopSourceRef runloopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
    2.16          if  (runloopSource) {
    2.17 -            tapdata->tap = eventTap;
    2.18              tapdata->runloopSource = runloopSource;
    2.19          } else {
    2.20              CFRelease(eventTap);
    2.21 @@ -202,15 +199,30 @@
    2.22  
    2.23      tapdata->runloopStartedSemaphore = SDL_CreateSemaphore(0);
    2.24      if (tapdata->runloopStartedSemaphore) {
    2.25 -        tapdata->thread = SDL_CreateThreadInternal(&Cocoa_MouseTapThread, "Event Tap Loop", 512 * 1024, tapdata);
    2.26 -        if (!tapdata->thread) {
    2.27 -            SDL_DestroySemaphore(tapdata->runloopStartedSemaphore);
    2.28 +        tapdata->tap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
    2.29 +                                        kCGEventTapOptionDefault, allGrabbedEventsMask,
    2.30 +                                        &Cocoa_MouseTapCallback, tapdata);
    2.31 +        if (tapdata->tap) {
    2.32 +            tapdata->thread = SDL_CreateThreadInternal(&Cocoa_MouseTapThread, "Event Tap Loop", 512 * 1024, tapdata);
    2.33 +            if (tapdata->thread) {
    2.34 +                /* Success - early out. Ownership transferred to thread. */
    2.35 +            	return;
    2.36 +            }
    2.37 +            CFRelease(tapdata->tap);
    2.38          }
    2.39 +        SDL_DestroySemaphore(tapdata->runloopStartedSemaphore);
    2.40      }
    2.41 +    SDL_free(driverdata->tapdata);
    2.42 +    driverdata->tapdata = NULL;
    2.43 +}
    2.44  
    2.45 -    if (!tapdata->thread) {
    2.46 -        SDL_free(driverdata->tapdata);
    2.47 -        driverdata->tapdata = NULL;
    2.48 +void
    2.49 +Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled)
    2.50 +{
    2.51 +    SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
    2.52 +    if (tapdata && tapdata->tap)
    2.53 +    {
    2.54 +        CGEventTapEnable(tapdata->tap, enabled);
    2.55      }
    2.56  }
    2.57  
    2.58 @@ -246,6 +258,11 @@
    2.59  }
    2.60  
    2.61  void
    2.62 +Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled)
    2.63 +{
    2.64 +}
    2.65 +
    2.66 +void
    2.67  Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
    2.68  {
    2.69  }
     3.1 --- a/src/video/cocoa/SDL_cocoawindow.m	Fri Nov 25 14:16:27 2016 -0500
     3.2 +++ b/src/video/cocoa/SDL_cocoawindow.m	Sat Nov 26 10:26:22 2016 -0800
     3.3 @@ -38,6 +38,7 @@
     3.4  #include "SDL_cocoavideo.h"
     3.5  #include "SDL_cocoashape.h"
     3.6  #include "SDL_cocoamouse.h"
     3.7 +#include "SDL_cocoamousetap.h"
     3.8  #include "SDL_cocoaopengl.h"
     3.9  #include "SDL_assert.h"
    3.10  
    3.11 @@ -1634,8 +1635,13 @@
    3.12  void
    3.13  Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
    3.14  {
    3.15 +    SDL_Mouse *mouse = SDL_GetMouse();
    3.16 +    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    3.17 +
    3.18 +    /* Enable or disable the event tap as necessary */
    3.19 +    Cocoa_EnableMouseEventTap(mouse->driverdata, grabbed);
    3.20 +
    3.21      /* Move the cursor to the nearest point in the window */
    3.22 -    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    3.23      if (grabbed && data && ![data->listener isMoving]) {
    3.24          int x, y;
    3.25          CGPoint cgpoint;