Search code examples
c#multithreadingsdl-2

How do I send an application-defined message to the event loop in SDL?


I'm just getting started in SDL2 because of the real promise of having portable UI in C#. I'm something of a fan of the idea of one window, one canvas, one event loop anyway. Makes certain things simpler in basic modeling. But that means right now I need to ask very basic questions.

I have a foreground thread that enters the event loop. At some point a background thread needs to tell the foreground thread that application state changed and it needs to redraw something (or everything as the case may be). SDL has application events but I can't figure out how to send them.

void redraw() {
    var surface = SDL_GetWindowSurface(window);
    SDL_FillRect(surface, IntPtr.Zero, SDL_MapRGB(surface.GetPixelFormat(), 0x9F, 0x9F, 0xFF));
    SDL_UpdateWindowSurface(window);
}
new Thread(() => {
    Thread.Sleep(30000);
    /* SEND EVENT HERE */
}).Start();
bool done = false;
while (!done && SDL_WaitEvent(out var ev) != 0) {
    switch (ev.type) {
        case SDL_USEREVENT:
            redraw();
            break;
        case SDL_WINDOWEVENT:
            switch (ev.window.windowEvent) {
                case SDL_WINDOWEVENT_CLOSE:
                    SDL_DestroyWindow(window);
                    done = true;
                    break;
            }
            break;
}

but I can't find how to send the user event from the other thread.

Don't tell me to use an SDL timer. That's boilerplate. The real code is something else.


Solution

  • So the immediate fix to send the event (BAD CODE ALERT):

    new Thread(() => {
        Thread.Sleep(30000);
        SDL_Event sdlevent = new SDL_Event();
        sdlevent.type = SDL_USEREVENT;
        SDL_PushEvent(ref sdlevent);
    }).Start();
    

    But this code is wrong in case of somebody else registering an event. We need to register an event, get the ID, and use it.

    var myevent = (SDL_EventType)SDL_RegisterEvents(1);
    new Thread(() => {
        Thread.Sleep(30000);
        SDL_Event sdlevent = new SDL_Event();
        sdlevent.type = myevent;
        SDL_PushEvent(ref sdlevent);
    }).Start();
    

    And the case line now reads

                case var typemyevent when typemyevent == myevent:
    

    I'm not sure whether to be more embarrassed for C# or SDL for that case line but that's what it is.