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