Timer support for SDL backend

This commit is contained in:
Magnus Norddahl 2025-07-29 18:37:12 +02:00
commit 7d5c1bb2e4
2 changed files with 64 additions and 3 deletions

View file

@ -365,16 +365,55 @@ void SDL2DisplayWindow::ExitLoop()
ExitRunLoop = true;
}
std::unordered_map<void *, std::function<void()>> SDL2DisplayWindow::Timers;
std::unordered_map<void *, void *> SDL2DisplayWindow::TimerHandles;
unsigned long SDL2DisplayWindow::TimerIDs = 0;
Uint32 TimerEventID = SDL_RegisterEvents(1);
Uint32 SDL2DisplayWindow::ExecTimer(Uint32 interval, void* execID)
{
// cancel event and stop loop if function not found
if (Timers.find(execID) == Timers.end())
return 0;
SDL_Event timerEvent;
SDL_zero(timerEvent);
timerEvent.user.type = TimerEventID;
timerEvent.user.data1 = execID;
SDL_PushEvent(&timerEvent);
return interval;
}
void* SDL2DisplayWindow::StartTimer(int timeoutMilliseconds, std::function<void()> onTimer)
{
// To do: implement timers
CheckInitSDL();
return nullptr;
void* execID = (void*)(uintptr_t)++TimerIDs;
void* id = (void*)(uintptr_t)SDL_AddTimer(timeoutMilliseconds, SDL2DisplayWindow::ExecTimer, execID);
if (!id) return id;
Timers.insert({execID, onTimer});
TimerHandles.insert({id, execID});
return id;
}
void SDL2DisplayWindow::StopTimer(void* timerID)
{
// To do: implement timers
CheckInitSDL();
SDL_RemoveTimer((SDL_TimerID)(uintptr_t)timerID);
auto execID = TimerHandles.find(timerID);
if (execID == TimerHandles.end())
return;
Timers.erase(execID->second);
TimerHandles.erase(timerID);
}
SDL2DisplayWindow* SDL2DisplayWindow::FindEventWindow(const SDL_Event& event)
@ -401,6 +440,10 @@ SDL2DisplayWindow* SDL2DisplayWindow::FindEventWindow(const SDL_Event& event)
void SDL2DisplayWindow::DispatchEvent(const SDL_Event& event)
{
// timers are created in a non-window context
if (event.type == TimerEventID)
return OnTimerEvent(event.user);
SDL2DisplayWindow* window = FindEventWindow(event);
if (!window) return;
@ -509,6 +552,17 @@ void SDL2DisplayWindow::OnPaintEvent()
WindowHost->OnWindowPaint();
}
void SDL2DisplayWindow::OnTimerEvent(const SDL_UserEvent& event)
{
auto func = Timers.find(event.data1);
// incase timer was cancelled before we get here
if (func == Timers.end())
return;
func->second();
}
InputKey SDL2DisplayWindow::ScancodeToInputKey(SDL_Scancode keycode)
{
switch (keycode)

View file

@ -67,6 +67,7 @@ public:
void OnMouseWheel(const SDL_MouseWheelEvent& event);
void OnMouseMotion(const SDL_MouseMotionEvent& event);
void OnPaintEvent();
static void OnTimerEvent(const SDL_UserEvent& event);
InputKey GetMouseButtonKey(const SDL_MouseButtonEvent& event);
@ -86,6 +87,7 @@ public:
static void* StartTimer(int timeoutMilliseconds, std::function<void()> onTimer);
static void StopTimer(void* timerID);
static Uint32 ExecTimer(Uint32 interval, void* id);
DisplayWindowHost* WindowHost = nullptr;
SDL2NativeHandle Handle;
@ -102,4 +104,9 @@ public:
static bool ExitRunLoop;
static Uint32 PaintEventNumber;
static std::unordered_map<int, SDL2DisplayWindow*> WindowList;
static std::unordered_map<void *, void *> TimerHandles;
static std::unordered_map<void *, std::function<void()>> Timers;
static unsigned long TimerIDs;
static Uint32 TimerEventNumber;
};