git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
539
deps/juce/modules/juce_events/native/juce_mac_MessageManager.mm
vendored
Normal file
539
deps/juce/modules/juce_events/native/juce_mac_MessageManager.mm
vendored
Normal file
@ -0,0 +1,539 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided under the terms of the ISC license
|
||||
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
|
||||
To use, copy, modify, and/or distribute this software for any purpose with or
|
||||
without fee is hereby granted provided that the above copyright notice and
|
||||
this permission notice appear in all copies.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
using AppFocusChangeCallback = void (*)();
|
||||
AppFocusChangeCallback appFocusChangeCallback = nullptr;
|
||||
|
||||
using CheckEventBlockedByModalComps = bool (*)(NSEvent*);
|
||||
CheckEventBlockedByModalComps isEventBlockedByModalComps = nullptr;
|
||||
|
||||
using MenuTrackingChangedCallback = void (*)(bool);
|
||||
MenuTrackingChangedCallback menuTrackingChangedCallback = nullptr;
|
||||
|
||||
//==============================================================================
|
||||
struct AppDelegateClass : public ObjCClass<NSObject>
|
||||
{
|
||||
AppDelegateClass() : ObjCClass<NSObject> ("JUCEAppDelegate_")
|
||||
{
|
||||
addMethod (@selector (applicationWillFinishLaunching:), applicationWillFinishLaunching, "v@:@");
|
||||
addMethod (@selector (applicationShouldTerminate:), applicationShouldTerminate, "I@:@");
|
||||
addMethod (@selector (applicationWillTerminate:), applicationWillTerminate, "v@:@");
|
||||
addMethod (@selector (application:openFile:), application_openFile, "c@:@@");
|
||||
addMethod (@selector (application:openFiles:), application_openFiles, "v@:@@");
|
||||
addMethod (@selector (applicationDidBecomeActive:), applicationDidBecomeActive, "v@:@");
|
||||
addMethod (@selector (applicationDidResignActive:), applicationDidResignActive, "v@:@");
|
||||
addMethod (@selector (applicationWillUnhide:), applicationWillUnhide, "v@:@");
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
|
||||
addMethod (@selector (getUrl:withReplyEvent:), getUrl_withReplyEvent, "v@:@@");
|
||||
addMethod (@selector (broadcastMessageCallback:), broadcastMessageCallback, "v@:@");
|
||||
addMethod (@selector (mainMenuTrackingBegan:), mainMenuTrackingBegan, "v@:@");
|
||||
addMethod (@selector (mainMenuTrackingEnded:), mainMenuTrackingEnded, "v@:@");
|
||||
addMethod (@selector (dummyMethod), dummyMethod, "v@:");
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
#if JUCE_PUSH_NOTIFICATIONS
|
||||
//==============================================================================
|
||||
addIvar<NSObject<NSApplicationDelegate, NSUserNotificationCenterDelegate>*> ("pushNotificationsDelegate");
|
||||
|
||||
addMethod (@selector (applicationDidFinishLaunching:), applicationDidFinishLaunching, "v@:@");
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
|
||||
addMethod (@selector (setPushNotificationsDelegate:), setPushNotificationsDelegate, "v@:@");
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
addMethod (@selector (application:didRegisterForRemoteNotificationsWithDeviceToken:), registeredForRemoteNotifications, "v@:@@");
|
||||
addMethod (@selector (application:didFailToRegisterForRemoteNotificationsWithError:), failedToRegisterForRemoteNotifications, "v@:@@");
|
||||
addMethod (@selector (application:didReceiveRemoteNotification:), didReceiveRemoteNotification, "v@:@@");
|
||||
#endif
|
||||
|
||||
registerClass();
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
#if JUCE_PUSH_NOTIFICATIONS
|
||||
static void 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);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static NSApplicationTerminateReply applicationShouldTerminate (id /*self*/, SEL, NSApplication*)
|
||||
{
|
||||
if (auto* app = JUCEApplicationBase::getInstance())
|
||||
{
|
||||
app->systemRequestedQuit();
|
||||
|
||||
if (! MessageManager::getInstance()->hasStopMessageBeenSent())
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
return NSTerminateNow;
|
||||
}
|
||||
|
||||
static void applicationWillTerminate (id /*self*/, SEL, NSNotification*)
|
||||
{
|
||||
JUCEApplicationBase::appWillTerminateByForce();
|
||||
}
|
||||
|
||||
static BOOL application_openFile (id /*self*/, SEL, NSApplication*, NSString* filename)
|
||||
{
|
||||
if (auto* app = JUCEApplicationBase::getInstance())
|
||||
{
|
||||
app->anotherInstanceStarted (quotedIfContainsSpaces (filename));
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
static void 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 (" "));
|
||||
}
|
||||
}
|
||||
|
||||
static void applicationDidBecomeActive (id /*self*/, SEL, NSNotification*) { focusChanged(); }
|
||||
static void applicationDidResignActive (id /*self*/, SEL, NSNotification*) { focusChanged(); }
|
||||
static void applicationWillUnhide (id /*self*/, SEL, NSNotification*) { focusChanged(); }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void mainMenuTrackingBegan (id /*self*/, SEL, NSNotification*)
|
||||
{
|
||||
if (menuTrackingChangedCallback != nullptr)
|
||||
menuTrackingChangedCallback (true);
|
||||
}
|
||||
|
||||
static void mainMenuTrackingEnded (id /*self*/, SEL, NSNotification*)
|
||||
{
|
||||
if (menuTrackingChangedCallback != nullptr)
|
||||
menuTrackingChangedCallback (false);
|
||||
}
|
||||
|
||||
static void dummyMethod (id /*self*/, SEL) {} // (used as a way of running a dummy thread)
|
||||
|
||||
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));
|
||||
s = s.unquoted().replace ("\"", "\\\"");
|
||||
|
||||
if (s.containsChar (' '))
|
||||
s = s.quoted();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#if JUCE_PUSH_NOTIFICATIONS
|
||||
//==============================================================================
|
||||
static void setPushNotificationsDelegate (id self, SEL, NSObject<NSApplicationDelegate, NSUserNotificationCenterDelegate>* delegate)
|
||||
{
|
||||
object_setInstanceVariable (self, "pushNotificationsDelegate", delegate);
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
// This is declared at file scope, so that it's guaranteed to be
|
||||
// constructed before and destructed after `appDelegate` (below)
|
||||
static AppDelegateClass appDelegateClass;
|
||||
|
||||
//==============================================================================
|
||||
struct AppDelegate
|
||||
{
|
||||
public:
|
||||
AppDelegate()
|
||||
{
|
||||
delegate = [appDelegateClass.createInstance() init];
|
||||
|
||||
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
|
||||
[center addObserver: delegate selector: @selector (mainMenuTrackingBegan:)
|
||||
name: NSMenuDidBeginTrackingNotification object: nil];
|
||||
[center addObserver: delegate selector: @selector (mainMenuTrackingEnded:)
|
||||
name: NSMenuDidEndTrackingNotification object: nil];
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
if (JUCEApplicationBase::isStandaloneApp())
|
||||
{
|
||||
[NSApp setDelegate: delegate];
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
|
||||
[[NSDistributedNotificationCenter defaultCenter] addObserver: delegate
|
||||
selector: @selector (broadcastMessageCallback:)
|
||||
name: getBroadcastEventName()
|
||||
object: nil
|
||||
suspensionBehavior: NSNotificationSuspensionBehaviorDeliverImmediately];
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
}
|
||||
else
|
||||
{
|
||||
[center addObserver: delegate selector: @selector (applicationDidResignActive:)
|
||||
name: NSApplicationDidResignActiveNotification object: NSApp];
|
||||
|
||||
[center addObserver: delegate selector: @selector (applicationDidBecomeActive:)
|
||||
name: NSApplicationDidBecomeActiveNotification object: NSApp];
|
||||
|
||||
[center addObserver: delegate selector: @selector (applicationWillUnhide:)
|
||||
name: NSApplicationWillUnhideNotification object: NSApp];
|
||||
}
|
||||
}
|
||||
|
||||
~AppDelegate()
|
||||
{
|
||||
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: delegate];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver: delegate];
|
||||
|
||||
if (JUCEApplicationBase::isStandaloneApp())
|
||||
{
|
||||
[NSApp setDelegate: nil];
|
||||
|
||||
[[NSDistributedNotificationCenter defaultCenter] removeObserver: delegate
|
||||
name: getBroadcastEventName()
|
||||
object: nil];
|
||||
}
|
||||
|
||||
[delegate release];
|
||||
}
|
||||
|
||||
static NSString* getBroadcastEventName()
|
||||
{
|
||||
return juceStringToNS ("juce_" + String::toHexString (File::getSpecialLocation (File::currentExecutableFile).hashCode64()));
|
||||
}
|
||||
|
||||
MessageQueue messageQueue;
|
||||
id delegate;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void MessageManager::runDispatchLoop()
|
||||
{
|
||||
if (quitMessagePosted.get() == 0) // check that the quit message wasn't already posted..
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
// must only be called by the message thread!
|
||||
jassert (isThisTheMessageThread());
|
||||
|
||||
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS
|
||||
@try
|
||||
{
|
||||
[NSApp run];
|
||||
}
|
||||
@catch (NSException* e)
|
||||
{
|
||||
// An AppKit exception will kill the app, but at least this provides a chance to log it.,
|
||||
std::runtime_error ex (std::string ("NSException: ") + [[e name] UTF8String] + ", Reason:" + [[e reason] UTF8String]);
|
||||
JUCEApplicationBase::sendUnhandledException (&ex, __FILE__, __LINE__);
|
||||
}
|
||||
@finally
|
||||
{
|
||||
}
|
||||
#else
|
||||
[NSApp run];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void shutdownNSApp()
|
||||
{
|
||||
[NSApp stop: nil];
|
||||
[NSEvent startPeriodicEventsAfterDelay: 0 withPeriod: 0.1];
|
||||
}
|
||||
|
||||
void MessageManager::stopDispatchLoop()
|
||||
{
|
||||
if (isThisTheMessageThread())
|
||||
{
|
||||
quitMessagePosted = true;
|
||||
shutdownNSApp();
|
||||
}
|
||||
else
|
||||
{
|
||||
struct QuitCallback : public CallbackMessage
|
||||
{
|
||||
QuitCallback() {}
|
||||
void messageCallback() override { MessageManager::getInstance()->stopDispatchLoop(); }
|
||||
};
|
||||
|
||||
(new QuitCallback())->post();
|
||||
}
|
||||
}
|
||||
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
|
||||
{
|
||||
jassert (millisecondsToRunFor >= 0);
|
||||
jassert (isThisTheMessageThread()); // must only be called by the message thread
|
||||
|
||||
auto endTime = Time::currentTimeMillis() + millisecondsToRunFor;
|
||||
|
||||
while (quitMessagePosted.get() == 0)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
auto msRemaining = endTime - Time::currentTimeMillis();
|
||||
|
||||
if (msRemaining <= 0)
|
||||
break;
|
||||
|
||||
CFRunLoopRunInMode (kCFRunLoopDefaultMode, jmin (1.0, msRemaining * 0.001), true);
|
||||
|
||||
if (NSEvent* e = [NSApp nextEventMatchingMask: NSEventMaskAny
|
||||
untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.001]
|
||||
inMode: NSDefaultRunLoopMode
|
||||
dequeue: YES])
|
||||
if (isEventBlockedByModalComps == nullptr || ! (*isEventBlockedByModalComps) (e))
|
||||
[NSApp sendEvent: e];
|
||||
}
|
||||
}
|
||||
|
||||
return quitMessagePosted.get() == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
void initialiseNSApplication();
|
||||
void initialiseNSApplication()
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
[NSApplication sharedApplication];
|
||||
}
|
||||
}
|
||||
|
||||
static std::unique_ptr<AppDelegate> appDelegate;
|
||||
|
||||
void MessageManager::doPlatformSpecificInitialisation()
|
||||
{
|
||||
if (appDelegate == nil)
|
||||
appDelegate.reset (new AppDelegate());
|
||||
}
|
||||
|
||||
void MessageManager::doPlatformSpecificShutdown()
|
||||
{
|
||||
appDelegate = nullptr;
|
||||
}
|
||||
|
||||
bool MessageManager::postMessageToSystemQueue (MessageBase* message)
|
||||
{
|
||||
jassert (appDelegate != nil);
|
||||
appDelegate->messageQueue.post (message);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MessageManager::broadcastMessage (const String& message)
|
||||
{
|
||||
NSDictionary* info = [NSDictionary dictionaryWithObject: juceStringToNS (message)
|
||||
forKey: nsStringLiteral ("message")];
|
||||
|
||||
[[NSDistributedNotificationCenter defaultCenter] postNotificationName: AppDelegate::getBroadcastEventName()
|
||||
object: nil
|
||||
userInfo: info];
|
||||
}
|
||||
|
||||
// Special function used by some plugin classes to re-post carbon events
|
||||
void __attribute__ ((visibility("default"))) repostCurrentNSEvent();
|
||||
void __attribute__ ((visibility("default"))) repostCurrentNSEvent()
|
||||
{
|
||||
struct EventReposter : public CallbackMessage
|
||||
{
|
||||
EventReposter() : e ([[NSApp currentEvent] retain]) {}
|
||||
~EventReposter() override { [e release]; }
|
||||
|
||||
void messageCallback() override
|
||||
{
|
||||
[NSApp postEvent: e atStart: YES];
|
||||
}
|
||||
|
||||
NSEvent* e;
|
||||
};
|
||||
|
||||
(new EventReposter())->post();
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_MAC
|
||||
struct MountedVolumeListChangeDetector::Pimpl
|
||||
{
|
||||
Pimpl (MountedVolumeListChangeDetector& d) : owner (d)
|
||||
{
|
||||
static ObserverClass cls;
|
||||
delegate = [cls.createInstance() init];
|
||||
ObserverClass::setOwner (delegate, this);
|
||||
|
||||
NSNotificationCenter* nc = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
|
||||
[nc addObserver: delegate selector: @selector (changed:) name: NSWorkspaceDidMountNotification object: nil];
|
||||
[nc addObserver: delegate selector: @selector (changed:) name: NSWorkspaceDidUnmountNotification object: nil];
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
}
|
||||
|
||||
~Pimpl()
|
||||
{
|
||||
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver: delegate];
|
||||
[delegate release];
|
||||
}
|
||||
|
||||
private:
|
||||
MountedVolumeListChangeDetector& owner;
|
||||
id delegate;
|
||||
|
||||
struct ObserverClass : public ObjCClass<NSObject>
|
||||
{
|
||||
ObserverClass() : ObjCClass<NSObject> ("JUCEDriveObserver_")
|
||||
{
|
||||
addIvar<Pimpl*> ("owner");
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
|
||||
addMethod (@selector (changed:), changed, "v@:@");
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
addProtocol (@protocol (NSTextInput));
|
||||
registerClass();
|
||||
}
|
||||
|
||||
static Pimpl* getOwner (id self) { return getIvar<Pimpl*> (self, "owner"); }
|
||||
static void setOwner (id self, Pimpl* owner) { object_setInstanceVariable (self, "owner", owner); }
|
||||
|
||||
static void changed (id self, SEL, NSNotification*)
|
||||
{
|
||||
getOwner (self)->owner.mountedVolumeListChanged();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
MountedVolumeListChangeDetector::MountedVolumeListChangeDetector() { pimpl.reset (new Pimpl (*this)); }
|
||||
MountedVolumeListChangeDetector::~MountedVolumeListChangeDetector() {}
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user