@@ -102,16 +102,30 @@ static RLimitInitialiser rLimitInitialiser; | |||||
#endif | #endif | ||||
//============================================================================== | //============================================================================== | ||||
#if ! JUCE_IOS | |||||
static String getOSXVersion() | |||||
{ | |||||
JUCE_AUTORELEASEPOOL | |||||
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile: | |||||
nsStringLiteral ("/System/Library/CoreServices/SystemVersion.plist")]; | |||||
return nsStringToJuce ([dict objectForKey: nsStringLiteral ("ProductVersion")]); | |||||
} | |||||
#endif | |||||
SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | ||||
{ | { | ||||
#if JUCE_IOS | #if JUCE_IOS | ||||
return iOS; | return iOS; | ||||
#else | #else | ||||
SInt32 versionMinor = 0; | |||||
OSErr err = Gestalt (gestaltSystemVersionMinor, &versionMinor); | |||||
(void) err; | |||||
jassert (err == noErr); | |||||
return (OperatingSystemType) (versionMinor + MacOSX_10_4 - 4); | |||||
StringArray parts; | |||||
parts.addTokens (getOSXVersion(), ".", String::empty); | |||||
jassert (parts[0].getIntValue() == 10); | |||||
const int major = parts[1].getIntValue(); | |||||
jassert (major > 2); | |||||
return (OperatingSystemType) (major + MacOSX_10_4 - 4); | |||||
#endif | #endif | ||||
} | } | ||||
@@ -120,13 +134,7 @@ String SystemStats::getOperatingSystemName() | |||||
#if JUCE_IOS | #if JUCE_IOS | ||||
return "iOS " + nsStringToJuce ([[UIDevice currentDevice] systemVersion]); | return "iOS " + nsStringToJuce ([[UIDevice currentDevice] systemVersion]); | ||||
#else | #else | ||||
SInt32 major, minor; | |||||
Gestalt (gestaltSystemVersionMajor, &major); | |||||
Gestalt (gestaltSystemVersionMinor, &minor); | |||||
String s ("Mac OSX "); | |||||
s << (int) major << '.' << (int) minor; | |||||
return s; | |||||
return "Mac OSX " + getOSXVersion(); | |||||
#endif | #endif | ||||
} | } | ||||
@@ -46,11 +46,15 @@ | |||||
//============================================================================== | //============================================================================== | ||||
#if JUCE_MAC | #if JUCE_MAC | ||||
#import <WebKit/WebKit.h> | #import <WebKit/WebKit.h> | ||||
#define Point CarbonDummyPointName | |||||
#define Component CarbonDummyCompName | |||||
#import <Carbon/Carbon.h> // still needed for SetSystemUIMode() | |||||
#undef Point | |||||
#undef Component | |||||
#import <IOKit/pwr_mgt/IOPMLib.h> | |||||
#if JUCE_SUPPORT_CARBON | |||||
#define Point CarbonDummyPointName | |||||
#define Component CarbonDummyCompName | |||||
#import <Carbon/Carbon.h> // still needed for SetSystemUIMode() | |||||
#undef Point | |||||
#undef Component | |||||
#endif | |||||
//============================================================================== | //============================================================================== | ||||
#elif JUCE_WINDOWS | #elif JUCE_WINDOWS | ||||
@@ -84,70 +84,6 @@ private: | |||||
} | } | ||||
}; | }; | ||||
//============================================================================== | |||||
class TemporaryMainMenuWithStandardCommands | |||||
{ | |||||
public: | |||||
TemporaryMainMenuWithStandardCommands() | |||||
: oldMenu (MenuBarModel::getMacMainMenu()), oldAppleMenu (nullptr) | |||||
{ | |||||
if (const PopupMenu* appleMenu = MenuBarModel::getMacExtraAppleItemsMenu()) | |||||
oldAppleMenu = new PopupMenu (*appleMenu); | |||||
MenuBarModel::setMacMainMenu (nullptr); | |||||
NSMenu* menu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("Edit")]; | |||||
NSMenuItem* item; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Cut"), nil) | |||||
action: @selector (cut:) keyEquivalent: nsStringLiteral ("x")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Copy"), nil) | |||||
action: @selector (copy:) keyEquivalent: nsStringLiteral ("c")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Paste"), nil) | |||||
action: @selector (paste:) keyEquivalent: nsStringLiteral ("v")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSApp mainMenu] addItemWithTitle: NSLocalizedString (nsStringLiteral ("Edit"), nil) | |||||
action: nil keyEquivalent: nsEmptyString()]; | |||||
[[NSApp mainMenu] setSubmenu: menu forItem: item]; | |||||
[menu release]; | |||||
// use a dummy modal component so that apps can tell that something is currently modal. | |||||
dummyModalComponent.enterModalState(); | |||||
} | |||||
~TemporaryMainMenuWithStandardCommands() | |||||
{ | |||||
MenuBarModel::setMacMainMenu (oldMenu, oldAppleMenu); | |||||
} | |||||
private: | |||||
MenuBarModel* oldMenu; | |||||
ScopedPointer<PopupMenu> oldAppleMenu; | |||||
// The OS view already plays an alert when clicking outside | |||||
// the modal comp, so this override avoids adding extra | |||||
// inappropriate noises when the cancel button is pressed. | |||||
// This override is also important because it stops the base class | |||||
// calling ModalComponentManager::bringToFront, which can get | |||||
// recursive when file dialogs are involved | |||||
class SilentDummyModalComp : public Component | |||||
{ | |||||
public: | |||||
SilentDummyModalComp() {} | |||||
void inputAttemptWhenModal() {} | |||||
}; | |||||
SilentDummyModalComp dummyModalComponent; | |||||
}; | |||||
static NSMutableArray* createAllowedTypesArray (const StringArray& filters) | static NSMutableArray* createAllowedTypesArray (const StringArray& filters) | ||||
{ | { | ||||
if (filters.size() == 0) | if (filters.size() == 0) | ||||
@@ -295,7 +295,12 @@ private: | |||||
if (NSNib* menuNib = [[[NSNib alloc] initWithNibNamed: @"RecentFilesMenuTemplate" bundle: nil] autorelease]) | if (NSNib* menuNib = [[[NSNib alloc] initWithNibNamed: @"RecentFilesMenuTemplate" bundle: nil] autorelease]) | ||||
{ | { | ||||
NSArray* array = nil; | NSArray* array = nil; | ||||
#if (! defined (MAC_OS_X_VERSION_10_8)) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 | |||||
[menuNib instantiateNibWithOwner: NSApp topLevelObjects: &array]; | [menuNib instantiateNibWithOwner: NSApp topLevelObjects: &array]; | ||||
#else | |||||
[menuNib instantiateWithOwner: NSApp topLevelObjects: &array]; | |||||
#endif | |||||
for (id object in array) | for (id object in array) | ||||
{ | { | ||||
@@ -303,9 +308,11 @@ private: | |||||
{ | { | ||||
if (NSArray* items = [object itemArray]) | if (NSArray* items = [object itemArray]) | ||||
{ | { | ||||
NSMenuItem* item = findRecentFilesItem (items); | |||||
recentItem = [item retain]; | |||||
break; | |||||
if (NSMenuItem* item = findRecentFilesItem (items)) | |||||
{ | |||||
recentItem = [item retain]; | |||||
break; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -529,6 +536,70 @@ private: | |||||
JuceMainMenuHandler* JuceMainMenuHandler::instance = nullptr; | JuceMainMenuHandler* JuceMainMenuHandler::instance = nullptr; | ||||
//============================================================================== | |||||
class TemporaryMainMenuWithStandardCommands | |||||
{ | |||||
public: | |||||
TemporaryMainMenuWithStandardCommands() | |||||
: oldMenu (MenuBarModel::getMacMainMenu()), oldAppleMenu (nullptr) | |||||
{ | |||||
if (const PopupMenu* appleMenu = MenuBarModel::getMacExtraAppleItemsMenu()) | |||||
oldAppleMenu = new PopupMenu (*appleMenu); | |||||
MenuBarModel::setMacMainMenu (nullptr); | |||||
NSMenu* menu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("Edit")]; | |||||
NSMenuItem* item; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Cut"), nil) | |||||
action: @selector (cut:) keyEquivalent: nsStringLiteral ("x")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Copy"), nil) | |||||
action: @selector (copy:) keyEquivalent: nsStringLiteral ("c")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Paste"), nil) | |||||
action: @selector (paste:) keyEquivalent: nsStringLiteral ("v")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSApp mainMenu] addItemWithTitle: NSLocalizedString (nsStringLiteral ("Edit"), nil) | |||||
action: nil keyEquivalent: nsEmptyString()]; | |||||
[[NSApp mainMenu] setSubmenu: menu forItem: item]; | |||||
[menu release]; | |||||
// use a dummy modal component so that apps can tell that something is currently modal. | |||||
dummyModalComponent.enterModalState(); | |||||
} | |||||
~TemporaryMainMenuWithStandardCommands() | |||||
{ | |||||
MenuBarModel::setMacMainMenu (oldMenu, oldAppleMenu); | |||||
} | |||||
private: | |||||
MenuBarModel* oldMenu; | |||||
ScopedPointer<PopupMenu> oldAppleMenu; | |||||
// The OS view already plays an alert when clicking outside | |||||
// the modal comp, so this override avoids adding extra | |||||
// inappropriate noises when the cancel button is pressed. | |||||
// This override is also important because it stops the base class | |||||
// calling ModalComponentManager::bringToFront, which can get | |||||
// recursive when file dialogs are involved | |||||
class SilentDummyModalComp : public Component | |||||
{ | |||||
public: | |||||
SilentDummyModalComp() {} | |||||
void inputAttemptWhenModal() {} | |||||
}; | |||||
SilentDummyModalComp dummyModalComponent; | |||||
}; | |||||
//============================================================================== | //============================================================================== | ||||
namespace MainMenuHelpers | namespace MainMenuHelpers | ||||
{ | { | ||||
@@ -666,4 +737,8 @@ void juce_initialiseMacMainMenu() | |||||
if (JuceMainMenuHandler::instance == nullptr) | if (JuceMainMenuHandler::instance == nullptr) | ||||
MainMenuHelpers::rebuildMainMenu (nullptr); | MainMenuHelpers::rebuildMainMenu (nullptr); | ||||
// Forcing a rebuild of the menus like this seems necessary to kick the native | |||||
// recent-files list into action.. (not sure precisely why though) | |||||
TemporaryMainMenuWithStandardCommands dummy; (void) dummy; | |||||
} | } |
@@ -230,24 +230,49 @@ Desktop::DisplayOrientation Desktop::getCurrentOrientation() const | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
#ifndef __POWER__ // Some versions of the SDK omit this function.. | |||||
extern "C" { extern OSErr UpdateSystemActivity (UInt8); } | |||||
#endif | |||||
class ScreenSaverDefeater : public Timer | class ScreenSaverDefeater : public Timer | ||||
{ | { | ||||
public: | public: | ||||
ScreenSaverDefeater() | ScreenSaverDefeater() | ||||
{ | { | ||||
startTimer (10000); | |||||
startTimer (5000); | |||||
timerCallback(); | timerCallback(); | ||||
} | } | ||||
void timerCallback() | void timerCallback() | ||||
{ | { | ||||
if (Process::isForegroundProcess()) | if (Process::isForegroundProcess()) | ||||
UpdateSystemActivity (1 /*UsrActivity*/); | |||||
{ | |||||
if (assertion == nullptr) | |||||
assertion = new PMAssertion(); | |||||
} | |||||
else | |||||
{ | |||||
assertion = nullptr; | |||||
} | |||||
} | } | ||||
struct PMAssertion | |||||
{ | |||||
PMAssertion() : assertionID (kIOPMNullAssertionID) | |||||
{ | |||||
IOReturn res = IOPMAssertionCreateWithName (kIOPMAssertionTypePreventUserIdleDisplaySleep, | |||||
kIOPMAssertionLevelOn, | |||||
CFSTR ("JUCE Playback"), | |||||
&assertionID); | |||||
jassert (res == kIOReturnSuccess); (void) res; | |||||
} | |||||
~PMAssertion() | |||||
{ | |||||
if (assertionID != kIOPMNullAssertionID) | |||||
IOPMAssertionRelease (assertionID); | |||||
} | |||||
IOPMAssertionID assertionID; | |||||
}; | |||||
ScopedPointer<PMAssertion> assertion; | |||||
}; | }; | ||||
static ScopedPointer<ScreenSaverDefeater> screenSaverDefeater; | static ScopedPointer<ScreenSaverDefeater> screenSaverDefeater; | ||||