| @@ -53,7 +53,7 @@ void ActionBroadcaster::CallbackReceiver::handleMessage (const Message& message) | |||
| ActionBroadcaster::ActionBroadcaster() | |||
| { | |||
| // are you trying to create this object before or after juce has been intialised?? | |||
| jassert (MessageManager::instance != nullptr); | |||
| jassert (MessageManager::getInstanceWithoutCreating() != nullptr); | |||
| callback.owner = this; | |||
| } | |||
| @@ -61,7 +61,7 @@ ActionBroadcaster::ActionBroadcaster() | |||
| ActionBroadcaster::~ActionBroadcaster() | |||
| { | |||
| // all event-based objects must be deleted BEFORE juce is shut down! | |||
| jassert (MessageManager::instance != nullptr); | |||
| jassert (MessageManager::getInstanceWithoutCreating() != nullptr); | |||
| } | |||
| void ActionBroadcaster::addActionListener (ActionListener* const listener) | |||
| @@ -26,7 +26,7 @@ | |||
| ChangeBroadcaster::ChangeBroadcaster() noexcept | |||
| { | |||
| // are you trying to create this object before or after juce has been intialised?? | |||
| jassert (MessageManager::instance != nullptr); | |||
| jassert (MessageManager::getInstanceWithoutCreating() != nullptr); | |||
| callback.owner = this; | |||
| } | |||
| @@ -34,7 +34,7 @@ ChangeBroadcaster::ChangeBroadcaster() noexcept | |||
| ChangeBroadcaster::~ChangeBroadcaster() | |||
| { | |||
| // all event-based objects must be deleted BEFORE juce is shut down! | |||
| jassert (MessageManager::instance != nullptr); | |||
| jassert (MessageManager::getInstanceWithoutCreating() != nullptr); | |||
| } | |||
| void ChangeBroadcaster::addChangeListener (ChangeListener* const listener) | |||
| @@ -26,33 +26,34 @@ | |||
| #ifndef __JUCE_CALLBACKMESSAGE_JUCEHEADER__ | |||
| #define __JUCE_CALLBACKMESSAGE_JUCEHEADER__ | |||
| #include "juce_Message.h" | |||
| #include "juce_MessageManager.h" | |||
| //============================================================================== | |||
| /** | |||
| A message that calls a custom function when it gets delivered. | |||
| A message that invokes a callback method when it gets delivered. | |||
| You can use this class to fire off actions that you want to be performed later | |||
| on the message thread. | |||
| Unlike other Message objects, these don't get sent to a MessageListener, you | |||
| just call the post() method to send them, and when they arrive, your | |||
| messageCallback() method will automatically be invoked. | |||
| To use it, create a subclass of CallbackMessage which implements the messageCallback() | |||
| method, then call post() to dispatch it. The event thread will then invoke your | |||
| messageCallback() method later on, and will automatically delete the message object | |||
| afterwards. | |||
| Always create an instance of a CallbackMessage on the heap, as it will be | |||
| Always create a new instance of a CallbackMessage on the heap, as it will be | |||
| deleted automatically after the message has been delivered. | |||
| @see MessageListener, MessageManager, ActionListener, ChangeListener | |||
| @see MessageManager, MessageListener, ActionListener, ChangeListener | |||
| */ | |||
| class JUCE_API CallbackMessage : public Message | |||
| class JUCE_API CallbackMessage : public MessageManager::MessageBase | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| CallbackMessage() noexcept; | |||
| CallbackMessage() noexcept {} | |||
| /** Destructor. */ | |||
| ~CallbackMessage(); | |||
| ~CallbackMessage() {} | |||
| //============================================================================== | |||
| /** Called when the message is delivered. | |||
| @@ -65,17 +66,7 @@ public: | |||
| */ | |||
| virtual void messageCallback() = 0; | |||
| /** Instead of sending this message to a MessageListener, just call this method | |||
| to post it to the event queue. | |||
| After you've called this, this object will belong to the MessageManager, | |||
| which will delete it later. So make sure you don't delete the object yourself, | |||
| call post() more than once, or call post() on a stack-based obect! | |||
| */ | |||
| void post(); | |||
| private: | |||
| //============================================================================== | |||
| // Avoid the leak-detector because for plugins, the host can unload our DLL with undelivered | |||
| // messages still in the system event queue. These aren't harmful, but can cause annoying assertions. | |||
| JUCE_DECLARE_NON_COPYABLE (CallbackMessage); | |||
| @@ -27,39 +27,35 @@ | |||
| #define __JUCE_MESSAGE_JUCEHEADER__ | |||
| class MessageListener; | |||
| class MessageManager; | |||
| //============================================================================== | |||
| /** The base class for objects that can be delivered to a MessageListener. | |||
| /** The base class for objects that can be sent to a MessageListener. | |||
| If you want to send a message that carries some kind of custom data, just | |||
| create a subclass of Message with some appropriate member variables to hold | |||
| your data. | |||
| Always create a new instance of a Message object on the heap, as it will be | |||
| deleted automatically after the message has been delivered. | |||
| @see MessageListener, MessageManager, ActionListener, ChangeListener | |||
| */ | |||
| class JUCE_API Message : public ReferenceCountedObject | |||
| class JUCE_API Message : public MessageManager::MessageBase | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates an uninitialised message. | |||
| The class's variables will also be left uninitialised. | |||
| */ | |||
| /** Creates an uninitialised message. */ | |||
| Message() noexcept; | |||
| ~Message(); | |||
| /** Destructor. */ | |||
| virtual ~Message(); | |||
| /** A typedef for pointers to messages. */ | |||
| typedef ReferenceCountedObjectPtr <Message> Ptr; | |||
| typedef ReferenceCountedObjectPtr<Message> Ptr; | |||
| //============================================================================== | |||
| private: | |||
| friend class MessageListener; | |||
| friend class MessageManager; | |||
| MessageListener* messageRecipient; | |||
| WeakReference<MessageListener> recipient; | |||
| void messageCallback(); | |||
| // Avoid the leak-detector because for plugins, the host can unload our DLL with undelivered | |||
| // messages still in the system event queue. These aren't harmful, but can cause annoying assertions. | |||
| @@ -23,33 +23,29 @@ | |||
| ============================================================================== | |||
| */ | |||
| MessageListener::MessageListener() noexcept | |||
| { | |||
| // are you trying to create a messagelistener before or after juce has been intialised?? | |||
| jassert (MessageManager::instance != nullptr); | |||
| Message::Message() noexcept {} | |||
| Message::~Message() {} | |||
| if (MessageManager::instance != nullptr) | |||
| MessageManager::instance->messageListeners.add (this); | |||
| void Message::messageCallback() | |||
| { | |||
| MessageListener* const r = recipient; | |||
| if (r != nullptr) | |||
| r->handleMessage (*this); | |||
| } | |||
| MessageListener::~MessageListener() | |||
| MessageListener::MessageListener() noexcept | |||
| { | |||
| if (MessageManager::instance != nullptr) | |||
| MessageManager::instance->messageListeners.removeValue (this); | |||
| // Are you trying to create a messagelistener before or after juce has been intialised?? | |||
| jassert (MessageManager::getInstanceWithoutCreating() != nullptr); | |||
| } | |||
| void MessageListener::postMessage (Message* const message) const | |||
| MessageListener::~MessageListener() | |||
| { | |||
| message->messageRecipient = const_cast <MessageListener*> (this); | |||
| if (MessageManager::instance == nullptr) | |||
| MessageManager::getInstance(); | |||
| MessageManager::instance->postMessageToQueue (message); | |||
| masterReference.clear(); | |||
| } | |||
| bool MessageListener::isValidMessageListener() const noexcept | |||
| void MessageListener::postMessage (Message* const message) const | |||
| { | |||
| return MessageManager::instance != nullptr | |||
| && MessageManager::instance->messageListeners.contains (this); | |||
| message->recipient = const_cast <MessageListener*> (this); | |||
| message->post(); | |||
| } | |||
| @@ -26,7 +26,7 @@ | |||
| #ifndef __JUCE_MESSAGELISTENER_JUCEHEADER__ | |||
| #define __JUCE_MESSAGELISTENER_JUCEHEADER__ | |||
| #include "juce_Message.h" | |||
| #include "juce_MessageManager.h" | |||
| //============================================================================== | |||
| @@ -37,19 +37,11 @@ | |||
| */ | |||
| class JUCE_API MessageListener | |||
| { | |||
| protected: | |||
| //============================================================================== | |||
| /** Creates a MessageListener. */ | |||
| MessageListener() noexcept; | |||
| public: | |||
| //============================================================================== | |||
| /** Destructor. | |||
| MessageListener() noexcept; | |||
| When a MessageListener is deleted, it removes itself from a global list | |||
| of registered listeners, so that the isValidMessageListener() method | |||
| will no longer return true. | |||
| */ | |||
| /** Destructor. */ | |||
| virtual ~MessageListener(); | |||
| //============================================================================== | |||
| @@ -68,25 +60,15 @@ public: | |||
| This method can be called safely by any thread. | |||
| @param message the message object to send - this will be deleted | |||
| automatically by the message queue, so don't keep any | |||
| references to it after calling this method. | |||
| automatically by the message queue, so make sure it's | |||
| allocated on the heap, not the stack! | |||
| @see handleMessage | |||
| */ | |||
| void postMessage (Message* message) const; | |||
| //============================================================================== | |||
| /** Checks whether this MessageListener has been deleted. | |||
| Although not foolproof, this method is safe to call on dangling or null | |||
| pointers. A list of active MessageListeners is kept internally, so this | |||
| checks whether the object is on this list or not. | |||
| Note that it's possible to get a false-positive here, if an object is | |||
| deleted and another is subsequently created that happens to be at the | |||
| exact same memory location, but I can't think of a good way of avoiding | |||
| this. | |||
| */ | |||
| bool isValidMessageListener() const noexcept; | |||
| private: | |||
| WeakReference<MessageListener>::Master masterReference; | |||
| friend class WeakReference<MessageListener>; | |||
| }; | |||
| @@ -23,22 +23,7 @@ | |||
| ============================================================================== | |||
| */ | |||
| Message::Message() noexcept : messageRecipient (nullptr) {} | |||
| Message::~Message() {} | |||
| //============================================================================== | |||
| CallbackMessage::CallbackMessage() noexcept {} | |||
| CallbackMessage::~CallbackMessage() {} | |||
| void CallbackMessage::post() | |||
| { | |||
| MessageManager* const mm = MessageManager::instance; | |||
| if (mm != nullptr) | |||
| mm->postMessageToQueue (this); | |||
| } | |||
| //============================================================================== | |||
| class MessageManager::QuitMessage : public CallbackMessage | |||
| class MessageManager::QuitMessage : public MessageManager::MessageBase | |||
| { | |||
| public: | |||
| QuitMessage() {} | |||
| @@ -55,8 +40,6 @@ private: | |||
| }; | |||
| //============================================================================== | |||
| MessageManager* MessageManager::instance = nullptr; | |||
| MessageManager::MessageManager() noexcept | |||
| : quitMessagePosted (false), | |||
| quitMessageReceived (false), | |||
| @@ -73,13 +56,12 @@ MessageManager::~MessageManager() noexcept | |||
| doPlatformSpecificShutdown(); | |||
| // If you hit this assertion, then you've probably leaked some kind of MessageListener object.. | |||
| jassert (messageListeners.size() == 0); | |||
| jassert (instance == this); | |||
| instance = nullptr; // do this last in case this instance is still needed by doPlatformSpecificShutdown() | |||
| } | |||
| MessageManager* MessageManager::instance = nullptr; | |||
| MessageManager* MessageManager::getInstance() | |||
| { | |||
| if (instance == nullptr) | |||
| @@ -91,37 +73,23 @@ MessageManager* MessageManager::getInstance() | |||
| return instance; | |||
| } | |||
| void MessageManager::deleteInstance() | |||
| inline MessageManager* MessageManager::getInstanceWithoutCreating() noexcept | |||
| { | |||
| deleteAndZero (instance); | |||
| return instance; | |||
| } | |||
| void MessageManager::postMessageToQueue (Message* const message) | |||
| void MessageManager::deleteInstance() | |||
| { | |||
| if (quitMessagePosted || ! postMessageToSystemQueue (message)) | |||
| Message::Ptr deleter (message); // (this will delete messages that were just created with a 0 ref count) | |||
| deleteAndZero (instance); | |||
| } | |||
| //============================================================================== | |||
| void MessageManager::deliverMessage (Message* const message) | |||
| void MessageManager::MessageBase::post() | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| MessageListener* const recipient = message->messageRecipient; | |||
| if (recipient == nullptr) | |||
| { | |||
| CallbackMessage* const callbackMessage = dynamic_cast <CallbackMessage*> (message); | |||
| MessageManager* const mm = MessageManager::instance; | |||
| if (callbackMessage != nullptr) | |||
| callbackMessage->messageCallback(); | |||
| } | |||
| else if (messageListeners.contains (recipient)) | |||
| { | |||
| recipient->handleMessage (*message); | |||
| } | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| if (mm == nullptr || mm->quitMessagePosted || ! postMessageToSystemQueue (this)) | |||
| Ptr deleter (this); // (this will delete messages that were just created with a 0 ref count) | |||
| } | |||
| //============================================================================== | |||
| @@ -166,7 +134,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||
| #endif | |||
| //============================================================================== | |||
| class AsyncFunctionCallback : public CallbackMessage | |||
| class AsyncFunctionCallback : public MessageManager::MessageBase | |||
| { | |||
| public: | |||
| AsyncFunctionCallback (MessageCallbackFunction* const f, void* const param) | |||
| @@ -258,10 +226,10 @@ bool MessageManager::currentThreadHasLockedMessageManager() const noexcept | |||
| accessed from another thread inside a MM lock, you're screwed. (this is exactly what happens | |||
| in Cocoa). | |||
| */ | |||
| class MessageManagerLock::BlockingMessage : public CallbackMessage | |||
| class MessageManagerLock::BlockingMessage : public MessageManager::MessageBase | |||
| { | |||
| public: | |||
| BlockingMessage() {} | |||
| BlockingMessage() noexcept {} | |||
| void messageCallback() | |||
| { | |||
| @@ -26,7 +26,6 @@ | |||
| #ifndef __JUCE_MESSAGEMANAGER_JUCEHEADER__ | |||
| #define __JUCE_MESSAGEMANAGER_JUCEHEADER__ | |||
| #include "juce_CallbackMessage.h" | |||
| class MessageManagerLock; | |||
| class ThreadPoolJob; | |||
| class ActionListener; | |||
| @@ -40,9 +39,10 @@ typedef void* (MessageCallbackFunction) (void* userData); | |||
| //============================================================================== | |||
| /** Delivers Message objects to MessageListeners, and handles the event-dispatch loop. | |||
| /** | |||
| This class is in charge of the application's event-dispatch loop. | |||
| @see Message, MessageListener, MessageManagerLock, JUCEApplication | |||
| @see Message, CallbackMessage, MessageManagerLock, JUCEApplication | |||
| */ | |||
| class JUCE_API MessageManager | |||
| { | |||
| @@ -51,6 +51,9 @@ public: | |||
| /** Returns the global instance of the MessageManager. */ | |||
| static MessageManager* getInstance(); | |||
| /** Returns the global instance of the MessageManager, or nullptr if it doesn't exist. */ | |||
| static MessageManager* getInstanceWithoutCreating() noexcept; | |||
| /** Deletes the global MessageManager instance. | |||
| Does nothing if no instance had been created. | |||
| */ | |||
| @@ -156,10 +159,28 @@ public: | |||
| /** Deregisters a broadcast listener. */ | |||
| void deregisterBroadcastListener (ActionListener* listener); | |||
| //============================================================================== | |||
| /** Internal class used as the base class for all message objects. | |||
| You shouldn't need to use this directly - see the CallbackMessage or Message | |||
| classes instead. | |||
| */ | |||
| class JUCE_API MessageBase : public ReferenceCountedObject | |||
| { | |||
| public: | |||
| MessageBase() noexcept {} | |||
| virtual ~MessageBase() {} | |||
| virtual void messageCallback() = 0; | |||
| void post(); | |||
| typedef ReferenceCountedObjectPtr<MessageBase> Ptr; | |||
| JUCE_DECLARE_NON_COPYABLE (MessageBase); | |||
| }; | |||
| //============================================================================== | |||
| #ifndef DOXYGEN | |||
| // Internal methods - do not use! | |||
| void deliverMessage (Message*); | |||
| void deliverBroadcastMessage (const String&); | |||
| ~MessageManager() noexcept; | |||
| #endif | |||
| @@ -168,26 +189,20 @@ private: | |||
| //============================================================================== | |||
| MessageManager() noexcept; | |||
| friend class MessageListener; | |||
| friend class ChangeBroadcaster; | |||
| friend class ActionBroadcaster; | |||
| friend class CallbackMessage; | |||
| static MessageManager* instance; | |||
| SortedSet <const MessageListener*> messageListeners; | |||
| ScopedPointer <ActionBroadcaster> broadcaster; | |||
| friend class MessageBase; | |||
| class QuitMessage; | |||
| friend class QuitMessage; | |||
| friend class MessageManagerLock; | |||
| ScopedPointer <ActionBroadcaster> broadcaster; | |||
| bool quitMessagePosted, quitMessageReceived; | |||
| Thread::ThreadID messageThreadId; | |||
| friend class MessageManagerLock; | |||
| Thread::ThreadID volatile threadWithLock; | |||
| CriticalSection lockingLock; | |||
| void postMessageToQueue (Message*); | |||
| static bool postMessageToSystemQueue (Message*); | |||
| static bool postMessageToSystemQueue (MessageBase*); | |||
| static void* exitModalLoopCallback (void*); | |||
| static void doPlatformSpecificInitialisation(); | |||
| static void doPlatformSpecificShutdown(); | |||
| @@ -36,7 +36,7 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPend | |||
| } | |||
| //============================================================================== | |||
| bool MessageManager::postMessageToSystemQueue (Message* message) | |||
| bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message) | |||
| { | |||
| message->incReferenceCount(); | |||
| getEnv()->CallVoidMethod (android.activity, JuceAppActivity.postMessage, (jlong) (pointer_sized_uint) message); | |||
| @@ -45,9 +45,13 @@ bool MessageManager::postMessageToSystemQueue (Message* message) | |||
| JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, deliverMessage, void, (jobject activity, jlong value)) | |||
| { | |||
| Message* const message = (Message*) (pointer_sized_uint) value; | |||
| MessageManager::getInstance()->deliverMessage (message); | |||
| message->decReferenceCount(); | |||
| JUCE_TRY | |||
| { | |||
| MessageManager::MessageBase* const message = (MessageManager::MessageBase*) (pointer_sized_uint) value; | |||
| message->messageCallback(); | |||
| message->decReferenceCount(); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| } | |||
| //============================================================================== | |||
| @@ -58,45 +58,27 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||
| } | |||
| //============================================================================== | |||
| struct MessageDispatchSystem | |||
| { | |||
| MessageDispatchSystem() | |||
| : juceCustomMessageHandler (nil) | |||
| { | |||
| juceCustomMessageHandler = [[JuceCustomMessageHandler alloc] init]; | |||
| } | |||
| ~MessageDispatchSystem() | |||
| { | |||
| [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceCustomMessageHandler]; | |||
| [juceCustomMessageHandler release]; | |||
| } | |||
| JuceCustomMessageHandler* juceCustomMessageHandler; | |||
| MessageQueue messageQueue; | |||
| }; | |||
| static ScopedPointer<MessageDispatchSystem> dispatcher; | |||
| static ScopedPointer<MessageQueue> messageQueue; | |||
| void MessageManager::doPlatformSpecificInitialisation() | |||
| { | |||
| if (dispatcher == nullptr) | |||
| dispatcher = new MessageDispatchSystem(); | |||
| if (messageQueue == nullptr) | |||
| messageQueue = new MessageQueue(); | |||
| } | |||
| void MessageManager::doPlatformSpecificShutdown() | |||
| { | |||
| dispatcher = nullptr; | |||
| messageQueue = nullptr; | |||
| } | |||
| bool MessageManager::postMessageToSystemQueue (Message* message) | |||
| bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message) | |||
| { | |||
| if (dispatcher != nullptr) | |||
| dispatcher->messageQueue.post (message); | |||
| if (messageQueue != nullptr) | |||
| messageQueue->post (message); | |||
| return true; | |||
| } | |||
| void MessageManager::broadcastMessage (const String& value) | |||
| void MessageManager::broadcastMessage (const String&) | |||
| { | |||
| } | |||
| @@ -59,7 +59,7 @@ public: | |||
| } | |||
| //============================================================================== | |||
| void postMessage (Message* msg) | |||
| void postMessage (MessageManager::MessageBase* const msg) | |||
| { | |||
| const int maxBytesInSocketQueue = 128; | |||
| @@ -133,7 +133,7 @@ public: | |||
| private: | |||
| CriticalSection lock; | |||
| ReferenceCountedArray <Message> queue; | |||
| ReferenceCountedArray <MessageManager::MessageBase> queue; | |||
| int fd[2]; | |||
| int bytesInSocket; | |||
| int totalEventCount; | |||
| @@ -173,7 +173,7 @@ private: | |||
| return true; | |||
| } | |||
| Message::Ptr popNextMessage() | |||
| MessageManager::MessageBase::Ptr popNextMessage() | |||
| { | |||
| const ScopedLock sl (lock); | |||
| @@ -192,12 +192,17 @@ private: | |||
| bool dispatchNextInternalMessage() | |||
| { | |||
| const Message::Ptr msg (popNextMessage()); | |||
| const MessageManager::MessageBase::Ptr msg (popNextMessage()); | |||
| if (msg == nullptr) | |||
| return false; | |||
| MessageManager::getInstance()->deliverMessage (msg); | |||
| JUCE_TRY | |||
| { | |||
| msg->messageCallback(); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| return true; | |||
| } | |||
| }; | |||
| @@ -346,7 +351,7 @@ void MessageManager::doPlatformSpecificShutdown() | |||
| } | |||
| } | |||
| bool MessageManager::postMessageToSystemQueue (Message* message) | |||
| bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message) | |||
| { | |||
| if (LinuxErrorHandling::errorOccurred) | |||
| return false; | |||
| @@ -96,7 +96,7 @@ public: | |||
| delete this; | |||
| } | |||
| void postMessage (Message* const m) | |||
| void postMessage (MessageManager::MessageBase* const m) | |||
| { | |||
| messageQueue.post (m); | |||
| } | |||
| @@ -360,7 +360,7 @@ void MessageManager::doPlatformSpecificShutdown() | |||
| } | |||
| } | |||
| bool MessageManager::postMessageToSystemQueue (Message* message) | |||
| bool MessageManager::postMessageToSystemQueue (MessageBase* message) | |||
| { | |||
| juceAppDelegate->redirector->postMessage (message); | |||
| return true; | |||
| @@ -53,7 +53,7 @@ public: | |||
| CFRelease (runLoopSource); | |||
| } | |||
| void post (Message* const message) | |||
| void post (MessageManager::MessageBase* const message) | |||
| { | |||
| messages.add (message); | |||
| CFRunLoopSourceSignal (runLoopSource); | |||
| @@ -61,20 +61,26 @@ public: | |||
| } | |||
| private: | |||
| ReferenceCountedArray <Message, CriticalSection> messages; | |||
| ReferenceCountedArray <MessageManager::MessageBase, CriticalSection> messages; | |||
| CriticalSection lock; | |||
| CFRunLoopRef runLoop; | |||
| CFRunLoopSourceRef runLoopSource; | |||
| bool deliverNextMessage() | |||
| { | |||
| const Message::Ptr nextMessage (messages.removeAndReturn (0)); | |||
| const MessageManager::MessageBase::Ptr nextMessage (messages.removeAndReturn (0)); | |||
| if (nextMessage == nullptr) | |||
| return false; | |||
| JUCE_AUTORELEASEPOOL | |||
| MessageManager::getInstance()->deliverMessage (nextMessage); | |||
| JUCE_TRY | |||
| { | |||
| nextMessage->messageCallback(); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| return true; | |||
| } | |||
| @@ -31,40 +31,49 @@ CheckEventBlockedByModalComps isEventBlockedByModalComps = nullptr; | |||
| //============================================================================== | |||
| namespace WindowsMessageHelpers | |||
| { | |||
| const unsigned int specialId = WM_APP + 0x4400; | |||
| const unsigned int broadcastId = WM_APP + 0x4403; | |||
| const unsigned int specialId = WM_APP + 0x4400; | |||
| const unsigned int broadcastId = WM_APP + 0x4403; | |||
| const TCHAR messageWindowName[] = _T("JUCEWindow"); | |||
| ScopedPointer<HiddenMessageWindow> messageWindow; | |||
| void dispatchMessageFromLParam (LPARAM lParam) | |||
| { | |||
| MessageManager::MessageBase* const message = reinterpret_cast <MessageManager::MessageBase*> (lParam); | |||
| JUCE_TRY | |||
| { | |||
| message->messageCallback(); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| message->decReferenceCount(); | |||
| } | |||
| //============================================================================== | |||
| LRESULT CALLBACK messageWndProc (HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam) noexcept | |||
| { | |||
| JUCE_TRY | |||
| if (h == juce_messageWindowHandle) | |||
| { | |||
| if (h == juce_messageWindowHandle) | |||
| if (message == specialId) | |||
| { | |||
| if (message == specialId) | |||
| { | |||
| // these are trapped early in the dispatch call, but must also be checked | |||
| // here in case there are windows modal dialog boxes doing their own | |||
| // dispatch loop and not calling our version | |||
| // (These are trapped early in our dispatch loop, but must also be checked | |||
| // here in case some 3rd-party code is running the dispatch loop). | |||
| dispatchMessageFromLParam (lParam); | |||
| return 0; | |||
| } | |||
| else if (message == broadcastId) | |||
| { | |||
| const ScopedPointer<String> messageString ((String*) lParam); | |||
| MessageManager::getInstance()->deliverBroadcastMessage (*messageString); | |||
| return 0; | |||
| } | |||
| else if (message == WM_COPYDATA) | |||
| { | |||
| const COPYDATASTRUCT* const data = reinterpret_cast <const COPYDATASTRUCT*> (lParam); | |||
| Message* const message = reinterpret_cast <Message*> (lParam); | |||
| MessageManager::getInstance()->deliverMessage (message); | |||
| message->decReferenceCount(); | |||
| return 0; | |||
| } | |||
| else if (message == broadcastId) | |||
| if (data->dwData == broadcastId) | |||
| { | |||
| const ScopedPointer <String> messageString ((String*) lParam); | |||
| MessageManager::getInstance()->deliverBroadcastMessage (*messageString); | |||
| return 0; | |||
| } | |||
| else if (message == WM_COPYDATA && ((const COPYDATASTRUCT*) lParam)->dwData == broadcastId) | |||
| { | |||
| const COPYDATASTRUCT* data = (COPYDATASTRUCT*) lParam; | |||
| const String messageString (CharPointer_UTF32 ((const CharPointer_UTF32::CharType*) data->lpData), | |||
| data->cbData / sizeof (CharPointer_UTF32::CharType)); | |||
| @@ -73,7 +82,6 @@ namespace WindowsMessageHelpers | |||
| } | |||
| } | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| return DefWindowProc (h, message, wParam, lParam); | |||
| } | |||
| @@ -100,19 +108,18 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPend | |||
| { | |||
| if (m.message == specialId && m.hwnd == juce_messageWindowHandle) | |||
| { | |||
| Message* const message = reinterpret_cast <Message*> (m.lParam); | |||
| MessageManager::getInstance()->deliverMessage (message); | |||
| message->decReferenceCount(); | |||
| dispatchMessageFromLParam (m.lParam); | |||
| } | |||
| else if (m.message == WM_QUIT) | |||
| { | |||
| if (JUCEApplicationBase::getInstance() != nullptr) | |||
| JUCEApplicationBase::getInstance()->systemRequestedQuit(); | |||
| JUCEApplicationBase* const app = JUCEApplicationBase::getInstance(); | |||
| if (app != nullptr) | |||
| app->systemRequestedQuit(); | |||
| } | |||
| else if (isEventBlockedByModalComps == nullptr || ! isEventBlockedByModalComps (m)) | |||
| { | |||
| if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN) | |||
| && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd)) | |||
| && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd)) | |||
| { | |||
| // if it's someone else's window being clicked on, and the focus is | |||
| // currently on a juce window, pass the kb focus over.. | |||
| @@ -130,7 +137,7 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPend | |||
| return true; | |||
| } | |||
| bool MessageManager::postMessageToSystemQueue (Message* message) | |||
| bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message) | |||
| { | |||
| message->incReferenceCount(); | |||
| return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::specialId, 0, (LPARAM) message) != 0; | |||