Commit 1b2cb70ca053517be98e9369e5e5e039b180d430

Ryan C. Gordon 2015-02-19T19:55:30

Mac OS X: replace some deprecated APIs with modern equivalents (thanks, Alex!). Fixes Bugzilla #2858.

diff --git a/src/video/cocoa/SDL_cocoaevents.h b/src/video/cocoa/SDL_cocoaevents.h
index 687cf64..1d27bbf 100644
--- a/src/video/cocoa/SDL_cocoaevents.h
+++ b/src/video/cocoa/SDL_cocoaevents.h
@@ -25,6 +25,7 @@
 
 extern void Cocoa_RegisterApp(void);
 extern void Cocoa_PumpEvents(_THIS);
+extern void Cocoa_SuspendScreenSaver(_THIS);
 
 #endif /* _SDL_cocoaevents_h */
 
diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m
index 13aeb45..5102034 100644
--- a/src/video/cocoa/SDL_cocoaevents.m
+++ b/src/video/cocoa/SDL_cocoaevents.m
@@ -27,6 +27,11 @@
 #include "../../events/SDL_events_c.h"
 #include "SDL_assert.h"
 
+/* This define was added in the 10.9 SDK. */
+#ifndef kIOPMAssertPreventUserIdleDisplaySleep
+#define kIOPMAssertPreventUserIdleDisplaySleep kIOPMAssertionTypePreventUserIdleDisplaySleep
+#endif
+
 @interface SDLApplication : NSApplication
 
 - (void)terminate:(id)sender;
@@ -251,17 +256,24 @@ Cocoa_RegisterApp(void)
 { @autoreleasepool
 {
     /* This can get called more than once! Be careful what you initialize! */
-    ProcessSerialNumber psn;
-
-    if (!GetCurrentProcess(&psn)) {
-        TransformProcessType(&psn, kProcessTransformToForegroundApplication);
-        SetFrontProcess(&psn);
-    }
 
     if (NSApp == nil) {
         [SDLApplication sharedApplication];
         SDL_assert(NSApp != nil);
 
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+        if ([NSApp respondsToSelector:@selector(setActivationPolicy:)]) {
+#endif
+            [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+        } else {
+            ProcessSerialNumber psn = {0, kCurrentProcess};
+            TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+        }
+#endif
+
+        [NSApp activateIgnoringOtherApps:YES];
+
         if ([NSApp mainMenu] == nil) {
             CreateApplicationMenus();
         }
@@ -293,8 +305,8 @@ Cocoa_PumpEvents(_THIS)
 { @autoreleasepool
 {
     /* Update activity every 30 seconds to prevent screensaver */
-    if (_this->suspend_screensaver) {
-        SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
+    SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
+    if (_this->suspend_screensaver && !data->screensaver_use_iopm) {
         Uint32 now = SDL_GetTicks();
         if (!data->screensaver_activity ||
             SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
@@ -336,6 +348,35 @@ Cocoa_PumpEvents(_THIS)
     }
 }}
 
+void
+Cocoa_SuspendScreenSaver(_THIS)
+{ @autoreleasepool
+{
+    SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
+
+    if (!data->screensaver_use_iopm) {
+        return;
+    }
+
+    if (data->screensaver_assertion) {
+        IOPMAssertionRelease(data->screensaver_assertion);
+        data->screensaver_assertion = 0;
+    }
+
+    if (_this->suspend_screensaver) {
+        /* FIXME: this should ideally describe the real reason why the game
+         * called SDL_DisableScreenSaver. Note that the name is only meant to be
+         * seen by OS X power users. there's an additional optional human-readable
+         * (localized) reason parameter which we don't set.
+         */
+        NSString *name = [GetApplicationName() stringByAppendingString:@" using SDL_DisableScreenSaver"];
+        IOPMAssertionCreateWithDescription(kIOPMAssertPreventUserIdleDisplaySleep,
+                                           (CFStringRef) name,
+                                           NULL, NULL, NULL, 0, NULL,
+                                           &data->screensaver_assertion);
+    }
+}}
+
 #endif /* SDL_VIDEO_DRIVER_COCOA */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/cocoa/SDL_cocoavideo.h b/src/video/cocoa/SDL_cocoavideo.h
index 288c41f..cf254db 100644
--- a/src/video/cocoa/SDL_cocoavideo.h
+++ b/src/video/cocoa/SDL_cocoavideo.h
@@ -26,6 +26,7 @@
 #include "SDL_opengl.h"
 
 #include <ApplicationServices/ApplicationServices.h>
+#include <IOKit/pwr_mgt/IOPMLib.h>
 #include <Cocoa/Cocoa.h>
 
 #include "SDL_keycode.h"
@@ -51,6 +52,9 @@ typedef struct SDL_VideoData
     SDLTranslatorResponder *fieldEdit;
     NSInteger clipboard_count;
     Uint32 screensaver_activity;
+    BOOL screensaver_use_iopm;
+    IOPMAssertionID screensaver_assertion;
+
 } SDL_VideoData;
 
 /* Utility functions */
diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m
index ad4f14c..f31218b 100644
--- a/src/video/cocoa/SDL_cocoavideo.m
+++ b/src/video/cocoa/SDL_cocoavideo.m
@@ -76,6 +76,7 @@ Cocoa_CreateDevice(int devindex)
     device->GetDisplayModes = Cocoa_GetDisplayModes;
     device->SetDisplayMode = Cocoa_SetDisplayMode;
     device->PumpEvents = Cocoa_PumpEvents;
+    device->SuspendScreenSaver = Cocoa_SuspendScreenSaver;
 
     device->CreateWindow = Cocoa_CreateWindow;
     device->CreateWindowFrom = Cocoa_CreateWindowFrom;
@@ -148,6 +149,9 @@ Cocoa_VideoInit(_THIS)
     const char *hint = SDL_GetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES);
     data->allow_spaces = ( (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) && (!hint || (*hint != '0')) );
 
+    /* The IOPM assertion API can disable the screensaver as of 10.7. */
+    data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6;
+
     return 0;
 }