mirror of https://github.com/axmolengine/axmol.git
issue #2087: [dispatcher] Fixing BugTest/Bug422 crashes.
This commit is contained in:
parent
81d8558c3c
commit
111a2ef4de
|
@ -58,11 +58,17 @@ private:
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
EventDispatcher::EventListenerItem::~EventListenerItem()
|
||||||
|
{
|
||||||
|
CC_SAFE_RELEASE(this->node);
|
||||||
|
}
|
||||||
|
|
||||||
EventDispatcher::EventDispatcher()
|
EventDispatcher::EventDispatcher()
|
||||||
: _inDispatch(0)
|
: _inDispatch(0)
|
||||||
, _listeners(nullptr)
|
, _listeners(nullptr)
|
||||||
, _isEnabled(true)
|
, _isEnabled(true)
|
||||||
{
|
{
|
||||||
|
_toAddedListeners.reserve(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventDispatcher::~EventDispatcher()
|
EventDispatcher::~EventDispatcher()
|
||||||
|
@ -82,6 +88,8 @@ void EventDispatcher::addEventListenerWithItem(EventListenerItem* item)
|
||||||
_listeners = new std::map<std::string, std::vector<EventListenerItem*>*>();
|
_listeners = new std::map<std::string, std::vector<EventListenerItem*>*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_inDispatch == 0)
|
||||||
|
{
|
||||||
std::vector<EventListenerItem*>* listenerList = nullptr;
|
std::vector<EventListenerItem*>* listenerList = nullptr;
|
||||||
|
|
||||||
auto itr = _listeners->find(item->listener->type);
|
auto itr = _listeners->find(item->listener->type);
|
||||||
|
@ -98,9 +106,15 @@ void EventDispatcher::addEventListenerWithItem(EventListenerItem* item)
|
||||||
|
|
||||||
listenerList->insert(listenerList->begin(), item);
|
listenerList->insert(listenerList->begin(), item);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_toAddedListeners.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
|
void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
|
||||||
{
|
{
|
||||||
|
CCASSERT(listener && node, "Invalid parameters.");
|
||||||
CCASSERT(!listener->_isRegistered, "The listener has been registered.");
|
CCASSERT(!listener->_isRegistered, "The listener has been registered.");
|
||||||
|
|
||||||
if (!listener->checkAvaiable())
|
if (!listener->checkAvaiable())
|
||||||
|
@ -108,6 +122,7 @@ void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* list
|
||||||
|
|
||||||
auto item = new EventListenerItem();
|
auto item = new EventListenerItem();
|
||||||
item->node = node;
|
item->node = node;
|
||||||
|
item->node->retain();
|
||||||
item->fixedPriority = 0;
|
item->fixedPriority = 0;
|
||||||
item->listener = listener;
|
item->listener = listener;
|
||||||
item->listener->retain();
|
item->listener->retain();
|
||||||
|
@ -120,6 +135,7 @@ void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* list
|
||||||
|
|
||||||
void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)
|
void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)
|
||||||
{
|
{
|
||||||
|
CCASSERT(listener, "Invalid parameters.");
|
||||||
CCASSERT(!listener->_isRegistered, "The listener has been registered.");
|
CCASSERT(!listener->_isRegistered, "The listener has been registered.");
|
||||||
CCASSERT(fixedPriority != 0, "0 priority is forbidden for fixed priority since it's used for scene graph based priority.");
|
CCASSERT(fixedPriority != 0, "0 priority is forbidden for fixed priority since it's used for scene graph based priority.");
|
||||||
|
|
||||||
|
@ -141,6 +157,8 @@ void EventDispatcher::removeEventListener(EventListener* listener)
|
||||||
if (_listeners == nullptr || listener == nullptr)
|
if (_listeners == nullptr || listener == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
bool isFound = false;
|
||||||
|
|
||||||
for (auto iter = _listeners->begin(); iter != _listeners->end();)
|
for (auto iter = _listeners->begin(); iter != _listeners->end();)
|
||||||
{
|
{
|
||||||
for (auto itemIter = iter->second->begin(); itemIter != iter->second->end(); ++itemIter)
|
for (auto itemIter = iter->second->begin(); itemIter != iter->second->end(); ++itemIter)
|
||||||
|
@ -158,6 +176,7 @@ void EventDispatcher::removeEventListener(EventListener* listener)
|
||||||
(*itemIter)->listener = nullptr;
|
(*itemIter)->listener = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isFound = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,6 +191,9 @@ void EventDispatcher::removeEventListener(EventListener* listener)
|
||||||
{
|
{
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isFound)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_listeners->empty())
|
if (_listeners->empty())
|
||||||
|
@ -193,6 +215,9 @@ void EventDispatcher::setPriorityWithSceneGraph(EventListener* listener, Node* n
|
||||||
if (item->listener == listener)
|
if (item->listener == listener)
|
||||||
{
|
{
|
||||||
item->fixedPriority = 0;
|
item->fixedPriority = 0;
|
||||||
|
|
||||||
|
CC_SAFE_RETAIN(node);
|
||||||
|
CC_SAFE_RELEASE(item->node);
|
||||||
item->node = node;
|
item->node = node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -216,7 +241,7 @@ void EventDispatcher::setPriorityWithFixedValue(EventListener* listener, int fix
|
||||||
if (item->node != nullptr)
|
if (item->node != nullptr)
|
||||||
{
|
{
|
||||||
item->node->dissociateEventListener(listener);
|
item->node->dissociateEventListener(listener);
|
||||||
item->node = nullptr;
|
CC_SAFE_RELEASE_NULL(item->node);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -259,7 +284,7 @@ void EventDispatcher::dispatchEvent(Event* event, bool toSortListeners)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeUnregisteredListeners();
|
updateListenerItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
|
void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
|
||||||
|
@ -331,7 +356,7 @@ void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
|
||||||
if (touchEventListener->onTouchBegan)
|
if (touchEventListener->onTouchBegan)
|
||||||
{
|
{
|
||||||
isClaimed = touchEventListener->onTouchBegan(*touchesIter, event);
|
isClaimed = touchEventListener->onTouchBegan(*touchesIter, event);
|
||||||
if (isClaimed)
|
if (isClaimed && item->listener)
|
||||||
{
|
{
|
||||||
touchEventListener->_claimedTouches.push_back(*touchesIter);
|
touchEventListener->_claimedTouches.push_back(*touchesIter);
|
||||||
}
|
}
|
||||||
|
@ -355,14 +380,20 @@ void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
|
||||||
{
|
{
|
||||||
touchEventListener->onTouchEnded(*touchesIter, event);
|
touchEventListener->onTouchEnded(*touchesIter, event);
|
||||||
}
|
}
|
||||||
|
if (item->listener)
|
||||||
|
{
|
||||||
touchEventListener->_claimedTouches.erase(removedIter);
|
touchEventListener->_claimedTouches.erase(removedIter);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TouchEvent::EventCode::CANCELLED:
|
case TouchEvent::EventCode::CANCELLED:
|
||||||
if (touchEventListener->onTouchCancelled)
|
if (touchEventListener->onTouchCancelled)
|
||||||
{
|
{
|
||||||
touchEventListener->onTouchCancelled(*touchesIter, event);
|
touchEventListener->onTouchCancelled(*touchesIter, event);
|
||||||
}
|
}
|
||||||
|
if (item->listener)
|
||||||
|
{
|
||||||
touchEventListener->_claimedTouches.erase(removedIter);
|
touchEventListener->_claimedTouches.erase(removedIter);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CCASSERT(false, "The eventcode is invalid.");
|
CCASSERT(false, "The eventcode is invalid.");
|
||||||
|
@ -373,13 +404,13 @@ void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
|
||||||
// If the event was stopped, return directly.
|
// If the event was stopped, return directly.
|
||||||
if (event->isStopped())
|
if (event->isStopped())
|
||||||
{
|
{
|
||||||
removeUnregisteredListeners();
|
updateListenerItems();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCASSERT((*touchesIter)->getID() == (*mutableTouchesIter)->getID(), "");
|
CCASSERT((*touchesIter)->getID() == (*mutableTouchesIter)->getID(), "");
|
||||||
|
|
||||||
if (isClaimed && touchEventListener->_needSwallow)
|
if (isClaimed && item->listener && touchEventListener->_needSwallow)
|
||||||
{
|
{
|
||||||
if (isNeedsMutableSet)
|
if (isNeedsMutableSet)
|
||||||
{
|
{
|
||||||
|
@ -444,16 +475,16 @@ void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
|
||||||
// If the event was stopped, return directly.
|
// If the event was stopped, return directly.
|
||||||
if (event->isStopped())
|
if (event->isStopped())
|
||||||
{
|
{
|
||||||
removeUnregisteredListeners();
|
updateListenerItems();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeUnregisteredListeners();
|
updateListenerItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventDispatcher::removeUnregisteredListeners()
|
void EventDispatcher::updateListenerItems()
|
||||||
{
|
{
|
||||||
if (!_listeners)
|
if (!_listeners)
|
||||||
return;
|
return;
|
||||||
|
@ -461,16 +492,18 @@ void EventDispatcher::removeUnregisteredListeners()
|
||||||
auto listenerItemIter = _listeners->begin();
|
auto listenerItemIter = _listeners->begin();
|
||||||
while (listenerItemIter != _listeners->end())
|
while (listenerItemIter != _listeners->end())
|
||||||
{
|
{
|
||||||
auto removeIterBegin = std::remove_if(listenerItemIter->second->begin(), listenerItemIter->second->end(), [](const EventListenerItem* item){
|
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end();)
|
||||||
return item->listener == nullptr;
|
{
|
||||||
});
|
if ((*iter)->listener == nullptr)
|
||||||
|
|
||||||
for (auto iter = removeIterBegin; iter != listenerItemIter->second->end(); ++iter)
|
|
||||||
{
|
{
|
||||||
delete (*iter);
|
delete (*iter);
|
||||||
|
iter = listenerItemIter->second->erase(iter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listenerItemIter->second->erase(removeIterBegin, listenerItemIter->second->end());
|
|
||||||
|
|
||||||
if (listenerItemIter->second->empty())
|
if (listenerItemIter->second->empty())
|
||||||
{
|
{
|
||||||
|
@ -483,6 +516,29 @@ void EventDispatcher::removeUnregisteredListeners()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_toAddedListeners.empty())
|
||||||
|
{
|
||||||
|
std::vector<EventListenerItem*>* listenerList = nullptr;
|
||||||
|
|
||||||
|
for (auto& item : _toAddedListeners)
|
||||||
|
{
|
||||||
|
auto itr = _listeners->find(item->listener->type);
|
||||||
|
if (itr == _listeners->end())
|
||||||
|
{
|
||||||
|
listenerList = new std::vector<EventListenerItem*>();
|
||||||
|
listenerList->reserve(100);
|
||||||
|
_listeners->insert(std::make_pair(item->listener->type, listenerList));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listenerList = itr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
listenerList->push_back(item);
|
||||||
|
}
|
||||||
|
_toAddedListeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (_listeners->empty())
|
if (_listeners->empty())
|
||||||
{
|
{
|
||||||
delete _listeners;
|
delete _listeners;
|
||||||
|
@ -563,16 +619,24 @@ void EventDispatcher::removeListenersForEventType(const std::string& eventType)
|
||||||
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end(); ++iter)
|
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end(); ++iter)
|
||||||
{
|
{
|
||||||
(*iter)->listener->release();
|
(*iter)->listener->release();
|
||||||
|
if (_inDispatch)
|
||||||
|
{
|
||||||
|
(*iter)->listener = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
delete (*iter);
|
delete (*iter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_inDispatch)
|
||||||
|
{
|
||||||
listenerItemIter->second->clear();
|
listenerItemIter->second->clear();
|
||||||
|
|
||||||
delete listenerItemIter->second;
|
delete listenerItemIter->second;
|
||||||
|
|
||||||
_listeners->erase(listenerItemIter);
|
_listeners->erase(listenerItemIter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EventDispatcher::removeAllListeners()
|
void EventDispatcher::removeAllListeners()
|
||||||
{
|
{
|
||||||
|
@ -584,17 +648,29 @@ void EventDispatcher::removeAllListeners()
|
||||||
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end(); ++iter)
|
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end(); ++iter)
|
||||||
{
|
{
|
||||||
(*iter)->listener->release();
|
(*iter)->listener->release();
|
||||||
|
if (_inDispatch)
|
||||||
|
{
|
||||||
|
(*iter)->listener = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
delete (*iter);
|
delete (*iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
listenerItemIter->second->clear();
|
|
||||||
|
|
||||||
delete listenerItemIter->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_inDispatch)
|
||||||
|
{
|
||||||
|
listenerItemIter->second->clear();
|
||||||
|
delete listenerItemIter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_inDispatch)
|
||||||
|
{
|
||||||
delete _listeners;
|
delete _listeners;
|
||||||
_listeners = nullptr;
|
_listeners = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EventDispatcher::setEnabled(bool isEnabled)
|
void EventDispatcher::setEnabled(bool isEnabled)
|
||||||
{
|
{
|
||||||
|
|
|
@ -110,6 +110,7 @@ private:
|
||||||
int fixedPriority; // The higher the number, the higher the priority
|
int fixedPriority; // The higher the number, the higher the priority
|
||||||
Node* node; // Weak reference.
|
Node* node; // Weak reference.
|
||||||
EventListener* listener;
|
EventListener* listener;
|
||||||
|
~EventListenerItem();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Constructor of EventDispatcher */
|
/** Constructor of EventDispatcher */
|
||||||
|
@ -127,14 +128,18 @@ private:
|
||||||
/** Sorts the listeners of specified type by priority */
|
/** Sorts the listeners of specified type by priority */
|
||||||
void sortAllEventListenerItemsForType(const std::string& eventType);
|
void sortAllEventListenerItemsForType(const std::string& eventType);
|
||||||
|
|
||||||
/** Removes all listeners that have been unregistered. */
|
/** Updates all listener items
|
||||||
void removeUnregisteredListeners();
|
* 1) Removes all listener items that have been marked as 'removed' when dispatching event.
|
||||||
|
* 2) Adds all listener items that have been marked as 'added' when dispatching event.
|
||||||
|
*/
|
||||||
|
void updateListenerItems();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Listeners map.
|
* Listeners map.
|
||||||
*/
|
*/
|
||||||
std::map<std::string, std::vector<EventListenerItem*>*>* _listeners;
|
std::map<std::string, std::vector<EventListenerItem*>*>* _listeners;
|
||||||
|
std::vector<EventListenerItem*> _toAddedListeners;
|
||||||
|
|
||||||
int _inDispatch;
|
int _inDispatch;
|
||||||
bool _isEnabled;
|
bool _isEnabled;
|
||||||
|
|
Loading…
Reference in New Issue