For each keypress (and mouse action too) I get the following sequence:
SDL_PeepEvents( &event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT ) returns true, event is a proper event that happened.
SDL_PollEvent returns FALSE
SDL_PollEvent ran immedately again behaves as expected (returns the key event and true).
The application is single threaded, no event filters are used. SDL_PumpEvents is called before SDL_PeepEvents. I’ve just ported the same code from SDL 1.2 where it worked as I would expect it to work.
Did you mean SDL_PeepEvents?
Could be a window focus problem, but it’s strange that the peep returns the right event. Could you share a minimal reproducible example?
I could try to make a minimal reproducible example, but this is FreePascal, custom SDL bindings and a fairly complex custom engine loop - it would take a while to decouple all, and in the end I feel I’d have a properly working code whereas still not having any clue where the error in the engine could be :/.
Even switching to “official” bindings would take at least a day of work due to how things are set up, and it would be work wasted, as the official version doesn’t do what I need it to do (run-time loading).
I hoped someone had experience with a situation similar to this and has some insight where to look for potential problems.
When setting up a test what gets passed to Filter, we learn that a 32512 event is indeed passed through. Unfortunately this event is undocumented anywhere and isn’t picked up by anything.
Is this normal behaviour? Is it required to have a filter function that filters out unknown events?
Isn’t a garbage value because the same value gets passed to the filter function too!
In particular this is the function I tested to catch that value:
int filter(void *userdata, SDL_Event *event) {
switch (event->type) {
case SDL_KEYDOWN:
return 1;
case SDL_KEYUP:
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEWHEEL:
return 0;
}
printf("caught passthrough: %u\n", event->type);
return 1;
}
You just shouldn’t touch the event if the return value is 0!
Your polling should look like this:
while(SDL_PollEvent(&event)) {
// touch the event
}
Anyways I understood what’s causing your problem. Basically, it’s not a problem at all! Events are separated by SDL_POLLSENTINEL’s to create an event “groups” that you have to process in your event loop. Your event is in the next “group”, so you didn’t get in your first poll sequence. In other hand SDL_PeepEventswill show you this event no matter what.
Yeah, ask yourself if you really need SDL_PeepEvents. Usually SDL_PollEvent is all that you need.
Note that it’s possible to pass NULL as argument to SDL_PollEvent to check if there is another event without removing it from the queue. That doesn’t allow you to see the type of the next event but it’ll probably behave more consistent with your other calls to SDL_PollEvent.
If you want it to work like in SDL 1.2 and ignore the sentinel I think you just have to call SDL_PollEvent one extra time when it returns 0 to make sure there truly isn’t any events left.
while (SDL_PollEvent(&event) || SDL_PollEvent(&event)) {
// handle event
}
I haven’t actually tested this but I don’t see why it wouldn’t work. Whether it’s a good idea or not, I don’t know. The sentinel must have been added for a reason but I don’t know the details…
Thanks everyone for the help. Instead of the double Poll (which works BTW!) I went with filtering out any event that isn’t managed through a filter function and this works well too.
I need EventPending in this particular project, as parts of the game render in a loop until something happens, but have no idea what to do with the actual event itself - would require too much refactoring for barely any gain.
It seems like one of the reasons for the sentinel is to avoid having to call SDL_PumpEvents internally each time SDL_PollEvent is called. See https://github.com/libsdl-org/SDL/pull/4794. I suspect filtering out the sentinel will essentially undo this optimization.