Browse Source

MessageManager: Tidy up mac implementation

v7.0.9
reuk 2 years ago
parent
commit
95f823ff72
No known key found for this signature in database GPG Key ID: FCB43929F012EE5C
1 changed files with 145 additions and 169 deletions
  1. +145
    -169
      modules/juce_events/native/juce_mac_MessageManager.mm

+ 145
- 169
modules/juce_events/native/juce_mac_MessageManager.mm View File

@@ -35,151 +35,186 @@ MenuTrackingChangedCallback menuTrackingChangedCallback = nullptr;
//==============================================================================
struct AppDelegateClass : public ObjCClass<NSObject>
{
AppDelegateClass() : ObjCClass<NSObject> ("JUCEAppDelegate_")
AppDelegateClass() : ObjCClass ("JUCEAppDelegate_")
{
addMethod (@selector (applicationWillFinishLaunching:), applicationWillFinishLaunching);
addMethod (@selector (applicationShouldTerminate:), applicationShouldTerminate);
addMethod (@selector (applicationWillTerminate:), applicationWillTerminate);
addMethod (@selector (application:openFile:), application_openFile);
addMethod (@selector (application:openFiles:), application_openFiles);
addMethod (@selector (applicationDidBecomeActive:), applicationDidBecomeActive);
addMethod (@selector (applicationDidResignActive:), applicationDidResignActive);
addMethod (@selector (applicationWillUnhide:), applicationWillUnhide);
addMethod (@selector (applicationWillFinishLaunching:), [] (id self, SEL, NSNotification*)
{
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
[[NSAppleEventManager sharedAppleEventManager] setEventHandler: self
andSelector: @selector (getUrl:withReplyEvent:)
forEventClass: kInternetEventClass
andEventID: kAEGetURL];
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
});
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
addMethod (@selector (getUrl:withReplyEvent:), getUrl_withReplyEvent);
addMethod (@selector (broadcastMessageCallback:), broadcastMessageCallback);
addMethod (@selector (mainMenuTrackingBegan:), mainMenuTrackingBegan);
addMethod (@selector (mainMenuTrackingEnded:), mainMenuTrackingEnded);
addMethod (@selector (dummyMethod), dummyMethod);
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
addMethod (@selector (applicationShouldTerminate:), [] (id /*self*/, SEL, NSApplication*)
{
if (auto* app = JUCEApplicationBase::getInstance())
{
app->systemRequestedQuit();
#if JUCE_PUSH_NOTIFICATIONS
//==============================================================================
addIvar<NSObject<NSApplicationDelegate, NSUserNotificationCenterDelegate>*> ("pushNotificationsDelegate");
if (! MessageManager::getInstance()->hasStopMessageBeenSent())
return NSTerminateCancel;
}
addMethod (@selector (applicationDidFinishLaunching:), applicationDidFinishLaunching);
return NSTerminateNow;
});
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
addMethod (@selector (setPushNotificationsDelegate:), setPushNotificationsDelegate);
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
addMethod (@selector (applicationWillTerminate:), [] (id /*self*/, SEL, NSNotification*)
{
JUCEApplicationBase::appWillTerminateByForce();
});
addMethod (@selector (application:didRegisterForRemoteNotificationsWithDeviceToken:), registeredForRemoteNotifications);
addMethod (@selector (application:didFailToRegisterForRemoteNotificationsWithError:), failedToRegisterForRemoteNotifications);
addMethod (@selector (application:didReceiveRemoteNotification:), didReceiveRemoteNotification);
#endif
addMethod (@selector (application:openFile:), [] (id /*self*/, SEL, NSApplication*, NSString* filename)
{
if (auto* app = JUCEApplicationBase::getInstance())
{
app->anotherInstanceStarted (quotedIfContainsSpaces (filename));
return YES;
}
registerClass();
}
return NO;
});
addMethod (@selector (application:openFiles:), [] (id /*self*/, SEL, NSApplication*, NSArray* filenames)
{
if (auto* app = JUCEApplicationBase::getInstance())
{
StringArray files;
for (NSString* f in filenames)
files.add (quotedIfContainsSpaces (f));
if (files.size() > 0)
app->anotherInstanceStarted (files.joinIntoString (" "));
}
});
addMethod (@selector (applicationDidBecomeActive:), [] (id /*self*/, SEL, NSNotification*) { focusChanged(); });
addMethod (@selector (applicationDidResignActive:), [] (id /*self*/, SEL, NSNotification*) { focusChanged(); });
addMethod (@selector (applicationWillUnhide:), [] (id /*self*/, SEL, NSNotification*) { focusChanged(); });
private:
static void applicationWillFinishLaunching (id self, SEL, NSNotification*)
{
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
[[NSAppleEventManager sharedAppleEventManager] setEventHandler: self
andSelector: @selector (getUrl:withReplyEvent:)
forEventClass: kInternetEventClass
andEventID: kAEGetURL];
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
}
addMethod (@selector (getUrl:withReplyEvent:), [] (id /*self*/, SEL, NSAppleEventDescriptor* event, NSAppleEventDescriptor*)
{
if (auto* app = JUCEApplicationBase::getInstance())
app->anotherInstanceStarted (quotedIfContainsSpaces ([[event paramDescriptorForKeyword: keyDirectObject] stringValue]));
});
#if JUCE_PUSH_NOTIFICATIONS
static void applicationDidFinishLaunching (id self, SEL, NSNotification* notification)
{
if (notification.userInfo != nil)
addMethod (@selector (broadcastMessageCallback:), [] (id /*self*/, SEL, NSNotification* n)
{
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
// NSUserNotification is deprecated from macOS 11, but there doesn't seem to be a
// replacement for NSApplicationLaunchUserNotificationKey returning a non-deprecated type
NSUserNotification* userNotification = notification.userInfo[NSApplicationLaunchUserNotificationKey];
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
NSDictionary* dict = (NSDictionary*) [n userInfo];
auto messageString = nsStringToJuce ((NSString*) [dict valueForKey: nsStringLiteral ("message")]);
MessageManager::getInstance()->deliverBroadcastMessage (messageString);
});
if (userNotification != nil && userNotification.userInfo != nil)
didReceiveRemoteNotification (self, nil, [NSApplication sharedApplication], userNotification.userInfo);
}
}
#endif
addMethod (@selector (mainMenuTrackingBegan:), [] (id /*self*/, SEL, NSNotification*)
{
if (menuTrackingChangedCallback != nullptr)
menuTrackingChangedCallback (true);
});
static NSApplicationTerminateReply applicationShouldTerminate (id /*self*/, SEL, NSApplication*)
{
if (auto* app = JUCEApplicationBase::getInstance())
addMethod (@selector (mainMenuTrackingEnded:), [] (id /*self*/, SEL, NSNotification*)
{
app->systemRequestedQuit();
if (menuTrackingChangedCallback != nullptr)
menuTrackingChangedCallback (false);
});
if (! MessageManager::getInstance()->hasStopMessageBeenSent())
return NSTerminateCancel;
}
// (used as a way of running a dummy thread)
addMethod (@selector (dummyMethod), [] (id /*self*/, SEL) {});
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
return NSTerminateNow;
}
#if JUCE_PUSH_NOTIFICATIONS
//==============================================================================
addIvar<NSObject<NSApplicationDelegate, NSUserNotificationCenterDelegate>*> ("pushNotificationsDelegate");
static void applicationWillTerminate (id /*self*/, SEL, NSNotification*)
{
JUCEApplicationBase::appWillTerminateByForce();
}
addMethod (@selector (applicationDidFinishLaunching:), [] (id self, SEL, NSNotification* notification)
{
if (notification.userInfo != nil)
{
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
// NSUserNotification is deprecated from macOS 11, but there doesn't seem to be a
// replacement for NSApplicationLaunchUserNotificationKey returning a non-deprecated type
NSUserNotification* userNotification = notification.userInfo[NSApplicationLaunchUserNotificationKey];
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
if (userNotification != nil && userNotification.userInfo != nil)
didReceiveRemoteNotification (self, nil, [NSApplication sharedApplication], userNotification.userInfo);
}
});
static BOOL application_openFile (id /*self*/, SEL, NSApplication*, NSString* filename)
{
if (auto* app = JUCEApplicationBase::getInstance())
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
addMethod (@selector (setPushNotificationsDelegate:), [] (id self, SEL, NSObject<NSApplicationDelegate, NSUserNotificationCenterDelegate>* delegate)
{
app->anotherInstanceStarted (quotedIfContainsSpaces (filename));
return YES;
}
object_setInstanceVariable (self, "pushNotificationsDelegate", delegate);
});
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
return NO;
}
addMethod (@selector (application:didRegisterForRemoteNotificationsWithDeviceToken:), [] (id self, SEL, NSApplication* application, NSData* deviceToken)
{
auto* delegate = getPushNotificationsDelegate (self);
static void application_openFiles (id /*self*/, SEL, NSApplication*, NSArray* filenames)
{
if (auto* app = JUCEApplicationBase::getInstance())
SEL selector = @selector (application:didRegisterForRemoteNotificationsWithDeviceToken:);
if (delegate != nil && [delegate respondsToSelector: selector])
{
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [delegate methodSignatureForSelector: selector]];
[invocation setSelector: selector];
[invocation setTarget: delegate];
[invocation setArgument: &application atIndex:2];
[invocation setArgument: &deviceToken atIndex:3];
[invocation invoke];
}
});
addMethod (@selector (application:didFailToRegisterForRemoteNotificationsWithError:), [] (id self, SEL, NSApplication* application, NSError* error)
{
StringArray files;
auto* delegate = getPushNotificationsDelegate (self);
for (NSString* f in filenames)
files.add (quotedIfContainsSpaces (f));
SEL selector = @selector (application:didFailToRegisterForRemoteNotificationsWithError:);
if (files.size() > 0)
app->anotherInstanceStarted (files.joinIntoString (" "));
}
}
if (delegate != nil && [delegate respondsToSelector: selector])
{
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [delegate methodSignatureForSelector: selector]];
[invocation setSelector: selector];
[invocation setTarget: delegate];
[invocation setArgument: &application atIndex:2];
[invocation setArgument: &error atIndex:3];
static void applicationDidBecomeActive (id /*self*/, SEL, NSNotification*) { focusChanged(); }
static void applicationDidResignActive (id /*self*/, SEL, NSNotification*) { focusChanged(); }
static void applicationWillUnhide (id /*self*/, SEL, NSNotification*) { focusChanged(); }
[invocation invoke];
}
});
static void broadcastMessageCallback (id /*self*/, SEL, NSNotification* n)
{
NSDictionary* dict = (NSDictionary*) [n userInfo];
auto messageString = nsStringToJuce ((NSString*) [dict valueForKey: nsStringLiteral ("message")]);
MessageManager::getInstance()->deliverBroadcastMessage (messageString);
}
addMethod (@selector (application:didReceiveRemoteNotification:), [] (id self, SEL, NSApplication* application, NSDictionary* userInfo)
{
auto* delegate = getPushNotificationsDelegate (self);
static void mainMenuTrackingBegan (id /*self*/, SEL, NSNotification*)
{
if (menuTrackingChangedCallback != nullptr)
menuTrackingChangedCallback (true);
}
SEL selector = @selector (application:didReceiveRemoteNotification:);
static void mainMenuTrackingEnded (id /*self*/, SEL, NSNotification*)
{
if (menuTrackingChangedCallback != nullptr)
menuTrackingChangedCallback (false);
}
if (delegate != nil && [delegate respondsToSelector: selector])
{
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [delegate methodSignatureForSelector: selector]];
[invocation setSelector: selector];
[invocation setTarget: delegate];
[invocation setArgument: &application atIndex:2];
[invocation setArgument: &userInfo atIndex:3];
[invocation invoke];
}
});
#endif
static void dummyMethod (id /*self*/, SEL) {} // (used as a way of running a dummy thread)
registerClass();
}
private:
static void focusChanged()
{
if (appFocusChangeCallback != nullptr)
(*appFocusChangeCallback)();
}
static void getUrl_withReplyEvent (id /*self*/, SEL, NSAppleEventDescriptor* event, NSAppleEventDescriptor*)
{
if (auto* app = JUCEApplicationBase::getInstance())
app->anotherInstanceStarted (quotedIfContainsSpaces ([[event paramDescriptorForKeyword: keyDirectObject] stringValue]));
}
static String quotedIfContainsSpaces (NSString* file)
{
String s (nsStringToJuce (file));
@@ -191,71 +226,12 @@ private:
return s;
}
#if JUCE_PUSH_NOTIFICATIONS
//==============================================================================
static void setPushNotificationsDelegate (id self, SEL, NSObject<NSApplicationDelegate, NSUserNotificationCenterDelegate>* delegate)
{
object_setInstanceVariable (self, "pushNotificationsDelegate", delegate);
}
#if JUCE_PUSH_NOTIFICATIONS
static NSObject<NSApplicationDelegate, NSUserNotificationCenterDelegate>* getPushNotificationsDelegate (id self)
{
return getIvar<NSObject<NSApplicationDelegate, NSUserNotificationCenterDelegate>*> (self, "pushNotificationsDelegate");
}
static void registeredForRemoteNotifications (id self, SEL, NSApplication* application, NSData* deviceToken)
{
auto* delegate = getPushNotificationsDelegate (self);
SEL selector = @selector (application:didRegisterForRemoteNotificationsWithDeviceToken:);
if (delegate != nil && [delegate respondsToSelector: selector])
{
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [delegate methodSignatureForSelector: selector]];
[invocation setSelector: selector];
[invocation setTarget: delegate];
[invocation setArgument: &application atIndex:2];
[invocation setArgument: &deviceToken atIndex:3];
[invocation invoke];
}
}
static void failedToRegisterForRemoteNotifications (id self, SEL, NSApplication* application, NSError* error)
{
auto* delegate = getPushNotificationsDelegate (self);
SEL selector = @selector (application:didFailToRegisterForRemoteNotificationsWithError:);
if (delegate != nil && [delegate respondsToSelector: selector])
{
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [delegate methodSignatureForSelector: selector]];
[invocation setSelector: selector];
[invocation setTarget: delegate];
[invocation setArgument: &application atIndex:2];
[invocation setArgument: &error atIndex:3];
[invocation invoke];
}
}
static void didReceiveRemoteNotification (id self, SEL, NSApplication* application, NSDictionary* userInfo)
{
auto* delegate = getPushNotificationsDelegate (self);
SEL selector = @selector (application:didReceiveRemoteNotification:);
if (delegate != nil && [delegate respondsToSelector: selector])
{
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [delegate methodSignatureForSelector: selector]];
[invocation setSelector: selector];
[invocation setTarget: delegate];
[invocation setArgument: &application atIndex:2];
[invocation setArgument: &userInfo atIndex:3];
[invocation invoke];
}
}
#endif
};


Loading…
Cancel
Save