diff options
Diffstat (limited to 'src/player/EventDispatcher.cpp')
-rw-r--r-- | src/player/EventDispatcher.cpp | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/player/EventDispatcher.cpp b/src/player/EventDispatcher.cpp new file mode 100644 index 0000000..23caff2 --- /dev/null +++ b/src/player/EventDispatcher.cpp @@ -0,0 +1,184 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "EventDispatcher.h" +#include "Event.h" +#include "Player.h" +#include "Contact.h" +#include "CursorEvent.h" + +#include "../base/Exception.h" +#include "../base/OSHelper.h" + +#include <string> + +using namespace std; +using namespace boost; + +namespace avg { + +EventDispatcher::EventDispatcher(Player* pPlayer, bool bMouseEnabled) + : m_pPlayer(pPlayer), + m_NumMouseButtonsDown(0), + m_bMouseEnabled(bMouseEnabled) +{ +} + +EventDispatcher::~EventDispatcher() +{ +} + +void EventDispatcher::dispatch() +{ + vector<EventPtr> events; + + for (unsigned int i = 0; i < m_InputDevices.size(); ++i) { + IInputDevicePtr pCurInputDevice = m_InputDevices[i]; + + vector<EventPtr> curEvents = pCurInputDevice->pollEvents(); + vector<EventPtr>::iterator eventIt = curEvents.begin(); + events.insert(events.end(), curEvents.begin(), curEvents.end()); + + for ( ; eventIt != curEvents.end(); eventIt++) { + (*eventIt)->setInputDevice(pCurInputDevice); + } + } + + vector<EventPtr>::iterator it; + for (it = events.begin(); it != events.end(); ++it) { + EventPtr pEvent = *it; + bool bHookEatsEvent = processEventHook(pEvent); + if (!(!m_bMouseEnabled && pEvent->getSource() == Event::MOUSE) && + !bHookEatsEvent) { + testAddContact(pEvent); + handleEvent(*it); + testRemoveContact(pEvent); + } + } +} + +void EventDispatcher::addInputDevice(IInputDevicePtr pInputDevice) +{ + m_InputDevices.push_back(pInputDevice); +} + +void EventDispatcher::sendEvent(EventPtr pEvent) +{ + handleEvent(pEvent); +} + +void EventDispatcher::enableMouse(bool bEnabled) +{ + m_bMouseEnabled = bEnabled; +} + +ContactPtr EventDispatcher::getContact(int id) +{ + std::map<int, ContactPtr>::iterator it = m_ContactMap.find(id); + if (it == m_ContactMap.end()) { + return ContactPtr(); + } else { + return it->second; + } +} + +void EventDispatcher::handleEvent(EventPtr pEvent) +{ + m_pPlayer->handleEvent(pEvent); +} + +bool EventDispatcher::processEventHook(EventPtr pEvent) +{ + PyObject * pEventHook = m_pPlayer->getEventHook(); + if (pEventHook != Py_None) { + // If the hook returns true, stop processing the event + if (py::call<bool>(pEventHook, pEvent)) { + return true; + } + } + return false; +} + +void EventDispatcher::testAddContact(EventPtr pEvent) +{ + ContactPtr pContact; + CursorEventPtr pCursorEvent = dynamic_pointer_cast<CursorEvent>(pEvent); + if (pCursorEvent) { + switch (pCursorEvent->getType()) { + case Event::CURSOR_DOWN: + if (pCursorEvent->getSource() == Event::MOUSE) { + m_NumMouseButtonsDown++; + if (m_NumMouseButtonsDown == 1) { + AVG_ASSERT(!getContact(MOUSECURSORID)); + pContact = ContactPtr(new Contact(pCursorEvent)); + m_ContactMap[MOUSECURSORID] = pContact; + } + } else { + pContact = ContactPtr(new Contact(pCursorEvent)); + m_ContactMap[pCursorEvent->getCursorID()] = pContact; + } + break; + case Event::CURSOR_MOTION: + case Event::CURSOR_UP: { + pContact = getContact(pCursorEvent->getCursorID()); + AVG_ASSERT(pContact || ( + pCursorEvent->getSource() == Event::MOUSE && + m_NumMouseButtonsDown == 0)); + if (pContact) { + pContact->addEvent(pCursorEvent); + } + } + break; + case Event::CUSTOM_EVENT: + break; + default: + cerr << pCursorEvent->typeStr() << endl; + AVG_ASSERT(false); + break; + } + if (pContact) { + pCursorEvent->setContact(pContact); + } + } +} + +void EventDispatcher::testRemoveContact(EventPtr pEvent) +{ + if (pEvent->getType() == Event::CURSOR_UP) { + if (pEvent->getSource() == Event::MOUSE) { + // The following if is only false if the CURSOR_DOWN wasn't registered because + // it was outside the application window (or on the window border). + if (m_NumMouseButtonsDown > 0) { + m_NumMouseButtonsDown--; + if (m_NumMouseButtonsDown == 0) { + int rc = m_ContactMap.erase(MOUSECURSORID); + AVG_ASSERT(rc == 1); + } + } + } else { + int rc = m_ContactMap.erase( + dynamic_pointer_cast<CursorEvent>(pEvent)->getCursorID()); + AVG_ASSERT(rc == 1); + } + } +} + +} |