#include "event/Queue.hpp" #include "event/EvtContext.hpp" #include "event/EvtHandler.hpp" #include void UpdateSyncMouseState(EvtContext* context, MOUSEBUTTON button, int32_t down) { if (down) { context->m_queueSyncButtonState |= button; } else { context->m_queueSyncButtonState &= ~button; } } void UpdateSyncKeyState(EvtContext* context, KEY key, EVENTID& id) { context->m_critsect.Enter(); int32_t keyDown = 0; auto list = &context->m_queueSyncKeyDownList; for (auto node = list->Head(); node;) { if (node->key == key) { keyDown = 1; node = list->DeleteNode(node); } else { node = list->Next(node); } } if (id == EVENT_ID_KEYDOWN) { if (keyDown) { id = EVENT_ID_KEYDOWN_REPEATING; } auto node = context->m_queueSyncKeyDownList.NewNode(2, 0, 0); node->key = key; } context->m_critsect.Leave(); } void ResetSyncState(EvtContext* context) { context->m_queueSyncButtonState = 0; context->m_critsect.Enter(); context->m_queueSyncKeyDownList.Clear(); context->m_critsect.Leave(); } void UpdateSyncState(EvtContext* context, EVENTID& id, const void* data) { STORM_VALIDATE_BEGIN; STORM_VALIDATE(context); STORM_VALIDATE_END_VOID; switch (id) { case EVENT_ID_FOCUS: ResetSyncState(context); break; case EVENT_ID_KEYDOWN: case EVENT_ID_KEYUP: { auto key = reinterpret_cast(data)->key; UpdateSyncKeyState(context, key, id); break; } case EVENT_ID_MOUSEDOWN: case EVENT_ID_MOUSEUP: { auto button = reinterpret_cast(data)->button; UpdateSyncMouseState(context, button, id == EVENT_ID_MOUSEDOWN); break; } } } void IEvtQueueDispatch(EvtContext* context, EVENTID id, const void* data) { STORM_ASSERT(context); UpdateSyncState(context, id, data); // TODO // if (SErrIsDisplayingError()) { // return; // } auto handlerList = &context->m_queueHandlerList[id]; EvtHandler marker; marker.marker = 1; handlerList->LinkNode(&marker, 1, nullptr); EvtHandler* handler; while (1) { handler = marker.link.Next(); if (!handler) { break; } handlerList->LinkNode(&marker, 1, marker.link.Next()); if (!handler->marker && !handler->func(data, handler->param)) { break; } } handlerList->UnlinkNode(&marker); } void IEvtQueueDispatchAll(EvtContext* context) { // TODO } void IEvtQueueRegister(EvtContext* context, EVENTID id, int32_t (*handler)(const void*, void*), void* param, float priority) { STORM_ASSERT(context); auto handlerList = &context->m_queueHandlerList[id]; auto m = SMemAlloc(sizeof(EvtHandler), __FILE__, __LINE__, 0x8); auto evtHandler = new (m) EvtHandler(); evtHandler->priority = priority; evtHandler->param = param; evtHandler->func = handler; evtHandler->marker = 0; EvtHandler* h = handlerList->Head(); while (h && (priority < h->priority || h->marker)) { h = handlerList->Link(h)->Next(); } handlerList->LinkNode(evtHandler, 2, h); } int32_t IEvtQueueCheckSyncKeyState(EvtContext* context, KEY key) { STORM_VALIDATE_BEGIN; STORM_VALIDATE(context); STORM_VALIDATE_END; context->m_critsect.Enter(); int32_t keystate = 0; auto list = &context->m_queueSyncKeyDownList; for (auto node = list->Head(); node; node = list->Next(node)) { if (node->key == key) { keystate = 1; break; } } context->m_critsect.Leave(); return keystate; } void IEvtQueueUnregister(EvtContext* context, EVENTID id, EVENTHANDLERFUNC handler, void* param, uint32_t flags) { STORM_VALIDATE_BEGIN; STORM_VALIDATE(context); STORM_VALIDATE_END_VOID; auto idMatch = flags & 0x1; auto handlerMatch = flags & 0x2; auto paramMatch = flags & 0x4; for (uint32_t q = 0; q < EVENTIDS; q++) { auto listMatched = (!idMatch || q == id); if (listMatched) { auto handlerList = &context->m_queueHandlerList[q]; for (auto node = handlerList->Head(); node; node = handlerList->Next(node)) { auto nodeMatched = (!handlerMatch || node->func == handler) && (!paramMatch || node->param == param); if (nodeMatched && !node->marker) { node = handlerList->DeleteNode(node); } } } } }