1
0
forked from 0ad/0ad

A bunch of OS X SDK-related fixes.

Adds runtime support for 10.5 APIs: display modes, bundle paths, system
paths, pasteboards. Previously this was compile-time support only, which
prevented building on later SDKs while targeting earlier APIs.
Adds hardcoded version for pre-10.6 builds, to avoid messing with
deprecated Gestalt or having to add a 10.5 non-dispatch singleton (Grand
Central Dispatch didn't exist in 10.5)

This was SVN commit r14140.
This commit is contained in:
historic_bruno 2013-11-11 00:11:25 +00:00
parent 011cbb5725
commit 45a7f577d3
6 changed files with 169 additions and 117 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2010 Wildfire Games
/* Copyright (c) 2013 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -30,6 +30,7 @@
#include "lib/file/file.h"
#include "lib/posix/posix_filesystem.h" // mode_t
#include <AvailabilityMacros.h> // MAC_OS_X_VERSION_MIN_REQUIRED
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
@ -63,8 +64,7 @@ bool CanRunNotifications()
return false;
}
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
#else
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
#define kFSEventStreamCreateFlagFileEvents 0x00000010
#define kFSEventStreamEventFlagItemIsFile 0x00010000
#define kFSEventStreamEventFlagItemRemoved 0x00000200

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2012 Wildfire Games
/* Copyright (c) 2013 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -34,6 +34,13 @@
#include <CoreFoundation/CoreFoundation.h>
#include <mach-o/dyld.h> // _NSGetExecutablePath
// Ignore deprecation warnings for 10.5 backwards compatibility
#if GCC_VERSION >= 402 // (older GCCs don't support this pragma)
# if GCC_VERSION >= 406 // store user flags
# pragma GCC diagnostic push
# endif
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
Status sys_clipboard_set(const wchar_t* text)
{
@ -75,12 +82,6 @@ namespace gfx {
Status GetVideoMode(int* xres, int* yres, int* bpp, int* freq)
{
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
#else
CFDictionaryRef currentMode = CGDisplayCurrentMode(kCGDirectMainDisplay);
#endif
if(xres)
*xres = (int)CGDisplayPixelsWide(kCGDirectMainDisplay);
@ -91,39 +92,56 @@ Status GetVideoMode(int* xres, int* yres, int* bpp, int* freq)
{
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// CGDisplayBitsPerPixel was deprecated in OS X 10.6
CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(currentMode);
if (CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
*bpp = 32;
else if (CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
*bpp = 16;
else if (CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
*bpp = 8;
else // error
*bpp = 0;
if (CGDisplayCopyDisplayMode != NULL)
{
CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(currentMode);
if (CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
*bpp = 32;
else if (CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
*bpp = 16;
else if (CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
*bpp = 8;
else // error
*bpp = 0;
// We're responsible for this
CFRelease(pixelEncoding);
#else
CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(currentMode, kCGDisplayBitsPerPixel);
CFNumberGetValue(num, kCFNumberIntType, bpp);
// We're responsible for this
CFRelease(pixelEncoding);
CGDisplayModeRelease(currentMode);
}
else
{
#endif // fallback to 10.5 API
CFDictionaryRef currentMode = CGDisplayCurrentMode(kCGDirectMainDisplay);
CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(currentMode, kCGDisplayBitsPerPixel);
CFNumberGetValue(num, kCFNumberIntType, bpp);
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
}
#endif
}
if(freq)
{
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
*freq = (int)CGDisplayModeGetRefreshRate(currentMode);
#else
CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(currentMode, kCGDisplayRefreshRate);
CFNumberGetValue(num, kCFNumberIntType, freq);
if (CGDisplayCopyDisplayMode != NULL)
{
CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
*freq = (int)CGDisplayModeGetRefreshRate(currentMode);
// We're responsible for this
CGDisplayModeRelease(currentMode);
}
else
{
#endif // fallback to 10.5 API
CFDictionaryRef currentMode = CGDisplayCurrentMode(kCGDirectMainDisplay);
CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(currentMode, kCGDisplayRefreshRate);
CFNumberGetValue(num, kCFNumberIntType, freq);
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
}
#endif
}
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// We're responsible for this
CGDisplayModeRelease(currentMode);
#endif
return INFO::OK;
}
@ -161,3 +179,10 @@ OsPath sys_ExecutablePathname()
return path;
}
#if GCC_VERSION >= 402
# pragma GCC diagnostic warning "-Wdeprecated-declarations"
# if GCC_VERSION >= 406
# pragma GCC diagnostic pop // restore user flags
# endif
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2012 Wildfire Games
/* Copyright (c) 2013 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -58,18 +58,19 @@ std::string osx_GetBundlePath()
NSBundle *bundle = [NSBundle bundleWithIdentifier: [NSString stringWithUTF8String: BUNDLE_ID_STR]];
if (bundle != nil)
{
NSString *pathStr;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// Retrieve NSURL and convert to POSIX path, then get C-string
// encoded as UTF-8, and use it to construct std::string
// NSURL:path "If the receiver does not conform to RFC 1808, returns nil."
NSString *pathStr = [[bundle bundleURL] path];
#else
NSString *pathStr = [bundle bundlePath];
if ([bundle respondsToSelector: @selector(bundleURL)])
pathStr = [[bundle bundleURL] path];
else
#endif
pathStr = [bundle bundlePath];
if (pathStr != nil)
{
path = std::string([pathStr UTF8String]);
}
}
[pool drain];
@ -84,18 +85,19 @@ std::string osx_GetBundleResourcesPath()
NSBundle *bundle = [NSBundle bundleWithIdentifier: [NSString stringWithUTF8String: BUNDLE_ID_STR]];
if (bundle != nil)
{
NSString *pathStr;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// Retrieve NSURL and convert to POSIX path, then get C-string
// encoded as UTF-8, and use it to construct std::string
// NSURL:path "If the receiver does not conform to RFC 1808, returns nil."
NSString *pathStr = [[bundle resourceURL] path];
#else
NSString *pathStr = [bundle resourcePath];
if ([bundle respondsToSelector: @selector(resourceURL)])
pathStr = [[bundle resourceURL] path];
else
#endif
pathStr = [bundle resourcePath];
if (pathStr != nil)
{
path = std::string([pathStr UTF8String]);
}
}
[pool drain];
@ -110,18 +112,19 @@ std::string osx_GetBundleFrameworksPath()
NSBundle *bundle = [NSBundle bundleWithIdentifier: [NSString stringWithUTF8String: BUNDLE_ID_STR]];
if (bundle != nil)
{
NSString *pathStr;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// Retrieve NSURL and convert to POSIX path, then get C-string
// encoded as UTF-8, and use it to construct std::string
// NSURL:path "If the receiver does not conform to RFC 1808, returns nil."
NSString *pathStr = [[bundle privateFrameworksURL] path];
#else
NSString *pathStr = [bundle privateFrameworksPath];
if ([bundle respondsToSelector: @selector(privateFrameworksURL)])
pathStr = [[bundle privateFrameworksURL] path];
else
#endif
pathStr = [bundle privateFrameworksPath];
if (pathStr != nil)
{
path = std::string([pathStr UTF8String]);
}
}
[pool drain];

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2012 Wildfire Games
/* Copyright (c) 2013 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -33,22 +33,29 @@ bool osx_GetStringFromPasteboard(std::string& out)
NSString* string = nil;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// As of 10.6, pasteboards can hold multiple items
NSArray* classes = [NSArray arrayWithObjects:[NSString class], nil];
NSDictionary* options = [NSDictionary dictionary];
NSArray* copiedItems = [pasteboard readObjectsForClasses:classes options:options];
if (copiedItems != nil && [copiedItems count] > 0)
if ([pasteboard respondsToSelector: @selector(readObjectsForClasses:)])
{
NSArray* classes = [NSArray arrayWithObjects:[NSString class], nil];
NSDictionary* options = [NSDictionary dictionary];
NSArray* copiedItems = [pasteboard readObjectsForClasses:classes options:options];
// We only need to support a single item, so grab the first string
string = [copiedItems objectAtIndex:0];
if (copiedItems != nil && [copiedItems count] > 0)
string = [copiedItems objectAtIndex:0];
else
return false; // No strings found on pasteboard
}
else
return false; // No strings found on pasteboard
#else // 10.5
// Verify that there is a string available for us
NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil];
if ([pasteboard availableTypeFromArray:types] != nil)
string = [pasteboard stringForType:NSStringPboardType];
else
return false; // No strings found on pasteboard
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
{
#endif // fallback to 10.5 API
// Verify that there is a string available for us
NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil];
if ([pasteboard availableTypeFromArray:types] != nil)
string = [pasteboard stringForType:NSStringPboardType];
else
return false; // No strings found on pasteboard
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
}
#endif
if (string != nil)
out = std::string([string UTF8String]);
@ -63,15 +70,24 @@ bool osx_SendStringToPasteboard(const std::string& string)
// We're only working with strings, so we don't need to lazily write
// anything (otherwise we'd need to set up an owner and data provider)
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
NSString* type;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
NSString* type = NSPasteboardTypeString;
[pasteboard clearContents];
#else // 10.5
NSString* type = NSStringPboardType;
NSArray* types = [NSArray arrayWithObjects: type, nil];
// Roughly equivalent to clearContents followed by addTypes:owner
[pasteboard declareTypes:types owner:nil];
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
if ([pasteboard respondsToSelector: @selector(clearContents)])
{
type = NSPasteboardTypeString;
[pasteboard clearContents];
}
else
{
#endif // fallback to 10.5 API
type = NSStringPboardType;
NSArray* types = [NSArray arrayWithObjects: type, nil];
// Roughly equivalent to clearContents followed by addTypes:owner
[pasteboard declareTypes:types owner:nil];
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
}
#endif
// May raise a NSPasteboardCommunicationException
BOOL ok = [pasteboard setString:[NSString stringWithUTF8String:string.c_str()] forType:type];

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2012 Wildfire Games
/* Copyright (c) 2013 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -32,22 +32,28 @@ static std::string getUserDirectoryPath(NSSearchPathDirectory directory)
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
std::string result;
NSArray* paths;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// Returns array of NSURL objects which are preferred for file paths
NSArray* paths = [[NSFileManager defaultManager] URLsForDirectory:directory inDomains:NSUserDomainMask];
#else
NSArray* paths = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, true);
#endif
if ([NSFileManager instancesRespondToSelector:@selector(URLsForDirectory)])
paths = [[NSFileManager defaultManager] URLsForDirectory:directory inDomains:NSUserDomainMask];
else
#endif // fallback to 10.5 API
paths = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, true);
if ([paths count] > 0)
{
NSString* pathStr;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// Retrieve first NSURL and convert to POSIX path, then get C-string
// encoded as UTF-8, and use it to construct std::string
// NSURL:path "If the receiver does not conform to RFC 1808, returns nil."
NSString* pathStr = [[paths objectAtIndex:0] path];
#else
NSString* pathStr = [paths objectAtIndex:0];
#endif
if ([NSFileManager instancesRespondToSelector:@selector(URLsForDirectory)])
pathStr = [[paths objectAtIndex:0] path];
else
#endif // fallback to 10.5 API
pathStr = [paths objectAtIndex:0];
if (pathStr != nil)
result = std::string([pathStr UTF8String]);
}

View File

@ -20,48 +20,50 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import <AvailabilityMacros.h> // MAC_OS_X_VERSION_MIN_REQUIRED
#import <Foundation/Foundation.h>
#import <dispatch/dispatch.h>
#import <string>
#import "osx_bundle.h"
#import "osx_sys_version.h"
#define STRINGIZE2(id) # id
#define STRINGIZE(id) STRINGIZE2(id)
// Pass the bundle identifier string as a build option
#ifdef BUNDLE_IDENTIFIER
static const char* BUNDLE_ID_STR = STRINGIZE(BUNDLE_IDENTIFIER);
#else
static const char* BUNDLE_ID_STR = "";
#endif
void GetSystemVersion( int &major, int &minor, int &bugfix )
void GetSystemVersion(int &major, int &minor, int &bugfix)
{
// sensible default
static int mMajor = 10;
static int mMinor = 8;
static int mBugfix = 0;
// grand central dispatch only available on 10.6+
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
if (dispatch_once != nil)
{
// sensible default
static int mMajor = 10;
static int mMinor = 8;
static int mBugfix = 0;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"];
NSArray* versions = [versionString componentsSeparatedByString:@"."];
check( versions.count >= 2 );
if ( versions.count >= 1 ) {
mMajor = [[versions objectAtIndex:0] integerValue];
}
if ( versions.count >= 2 ) {
mMinor = [[versions objectAtIndex:1] integerValue];
}
if ( versions.count >= 3 ) {
mBugfix = [[versions objectAtIndex:2] integerValue];
}
});
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"];
NSArray* versions = [versionString componentsSeparatedByString:@"."];
check(versions.count >= 2);
if (versions.count >= 1)
mMajor = [[versions objectAtIndex:0] integerValue];
if (versions.count >= 2)
mMinor = [[versions objectAtIndex:1] integerValue];
if (versions.count >= 3)
mBugfix = [[versions objectAtIndex:2] integerValue];
});
major = mMajor;
minor = mMinor;
bugfix = mBugfix;
major = mMajor;
minor = mMinor;
bugfix = mBugfix;
}
else
{
#endif // fallback to 10.5 API
// just return 10.5.0, it's unlikely we support an earlier OS
// and unlikely we care about bugfix versions
major = 10;
minor = 5;
bugfix = 0;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
}
#endif
}