Issue #6 resolved

sdl.ext.get_events() incorrectly handles more than 10 events

markhildreth
created an issue

When sdl.ext.get_events() is called, it tries to get the first 10 events off of the queue. If it does get 10 events, it tries to grab another ten. However, because it's using a pointer to the same array as the first call to store the results, any events found in the subsequent calls to SDL_PeepEvent overwrite the events found in the previous calls. Thus, if the events were numbered in the order that they are listed in the queue, you should see a list with the results of...

[1,2,3,4,5,6,7,8,9,10,11,12]

...but instead you would see..

[11,12,3,4,5,6,7,8,9,10,11,12]

This problem can be duplicated using the following code:

import sdl3 as sdl
import sdl2.ext as sdlext

sdl.SDL_Init(sdl.SDL_INIT_VIDEO)

# Clear all items from the event queue that might have happened when SDL started.
sdl.SDL_FlushEvent(sdl.SDL_FIRSTEVENT, sdl.SDL_LASTEVENT)

# Add a bunch of different events, at least 11 to duplicate issue
for x in range(12):
    event = sdl.SDL_Event()
    event.type = sdl.SDL_USEREVENT + x
    event.user = sdl.SDL_UserEvent(type=event.type, timestamp=0, windowID=0, code=0)
    sdl.SDL_PushEvent(event)

results = sdlext.get_events()

# This asserion should pass, as the first event we push is USEREVENT + 0, but it fails.
types_found = [x.type for x in results]
assert sdl.SDL_USEREVENT in types_found

A corrected version of get_events is shown below:

def get_events():
    """Gets all SDL events that are currently on the event queue."""
    events.SDL_PumpEvents()

    evlist = []
    SDL_PeepEvents = events.SDL_PeepEvents

    op = events.SDL_GETEVENT
    first = events.SDL_FIRSTEVENT
    last = events.SDL_LASTEVENT

    while True:
        evarray = (events.SDL_Event * 10)()
        ptr = ctypes.cast(evarray, ctypes.POINTER(events.SDL_Event))

        ret = SDL_PeepEvents(ptr, 10, op, first, last)
        if not ret:
            break

        evlist += list(evarray)[:ret]

    return evlist

Comments (2)

  1. Log in to comment