SFML community forums

Help => Window => Topic started by: Caeous on October 07, 2013, 02:43:08 pm

Title: Clear Keyboard Events in buffer
Post by: Caeous on October 07, 2013, 02:43:08 pm
Hello everyone,

I'm trying to replicate the functionality of FlushConsoleInputBuffer (for Console apps), and SDL_PeekEvent (with SDL_GETEVENT). They both give the ability to remove specific events from the queue.

This is useful is cases where the time it takes to process an event is much slower than the time it takes for the user to create an event. Example: Scrolling down a list with the keyboard arrows, if the user presses the keyboard too often - or through keyboard repeat - then the list will try to continue to scroll when it reaches the end, and you have to wait until all the events are done before you can do anything. In this case I'd like to clear the keyboard event buffer so that when the end of the list is reached the user can continue producing events.

I don't think I saw the ability to do this in SFML? Are there plans to introduce it? Are there any ways that I can do this?

Thanks guys,
Marc
Title: Re: Clear Keyboard Events in buffer
Post by: binary1248 on October 07, 2013, 03:15:14 pm
To empty the event queue of all events there was a similar question not so long ago:
http://en.sfml-dev.org/forums/index.php?topic=12886.0
SFML doesn't support selective emptying. Events are events to SFML.

If you are really having trouble coping with the rate at which keyboard events are generated, either your loop is really really slow, your operating system is set to produce insane amounts of events due to key repeat or the user has jack hammers primed on 5 keys at once and is hammering away at them. The latter 2 are very unlikely to be the case, so I would investigate the first possibility. Considering that in a typical application, hundreds of mouse move events are processed every second, I don't see how you can be experiencing such lag due to key events like you describe. Is there no way to speed up event processing? Perhaps you could provide an example of how you process these events e.g. how you would scroll this list.
Title: Re: Clear Keyboard Events in buffer
Post by: Caeous on October 07, 2013, 03:42:04 pm
Thanks for the response.

Yes, my loop is really really slow, I'm checking a MASSIVE database at every keyboard event.

There's not much that can be done about that unfortunately. This is a legacy application (20+ yrs old).

We're talking about ~2 seconds per keyboard event. So if you're scrolling down the list by pressing the keyboard arrow down multiple of times, it's going to take a while before you reach the bottom, and if you've pressed the arrow down too often, sometimes you have to wait 10 seconds before you can start doing something else again. It really sucks.

Perhaps instead of having something to clear the buffer, wouldn't it useful to be able to just get all the current events in the buffer - and simultaneously clear them - and then you can handle them as you wish?

Something along the lines of:

std::vector< sf::Event > sf::Window::getEvents() const
Title: Re: Clear Keyboard Events in buffer
Post by: Laurent on October 07, 2013, 03:50:43 pm
You should put your massive database check in a thread, so that the UI thread is never blocked. Then you can ignore all the scroll events that occur until the task is finished.
Title: Re: Clear Keyboard Events in buffer
Post by: Caeous on October 07, 2013, 04:00:29 pm
Sorry guys,

I should have been more specific; The database check doesn't occur at every keyboard event in the main input/event handler, but only when you're in this specific list. Yes, multithreading the database would have been a good solution then.

I'm dependent on this database check in the main thread as I need to process the results. We're essentially going through the list and then choosing an item.

Thanks for taking the time to answer my question.

Marc
Title: Re: Clear Keyboard Events in buffer
Post by: Laurent on October 07, 2013, 04:28:56 pm
Quote
Something along the lines of:

std::vector< sf::Event > sf::Window::getEvents() const

std::vector<sf::Event> getEvents(sf::Window& window)
{
    std::vector<sf::Event> events;
    sf::Event event;
    while (window.pollEvent(event))
        allEvents.push_back(event);
    return events;
}
?
Title: Re: Clear Keyboard Events in buffer
Post by: Caeous on October 07, 2013, 04:37:53 pm
That's potentially dangerous if events keep coming (continuously pressing key, or mouse move, etc).

You'd have to know how many events there are in the queue at the moment that you want to clear the buffer.

Perhaps in the form of:
int sf::Window::getEventCount()

std::vector<sf::Event> getEvents(sf::Window& window)
{
    std::vector<sf::Event> events;
    sf::Event event;
    int eventCount = window.getEventCount();
    while ( eventCount > 0 && window.pollEvent(event))
    {
        events.push_back(event);
        eventCount--;
    }
    return events;
}
 
Title: Re: Clear Keyboard Events in buffer
Post by: Laurent on October 07, 2013, 04:43:58 pm
Quote
That's potentially dangerous if events keep coming (continuously pressing key, or mouse move, etc).
It's not more dangerous than the polling loop that everyone (including you, if your app is well written) has in its main loop. It's the same, the only modification is that events are stored instead of processed immediately.
Title: Re: Clear Keyboard Events in buffer
Post by: Caeous on October 07, 2013, 05:54:11 pm
Yes, obviously in a situation where there's a main loop that would work.

Unfortunately, this is a legacy application, and the original creator decided to allow only one event to be handled at a time. We handle input in a whole bunch of places (I hate it).

As a result, having a vector of events is of no use to me (I was merely suggesting it since others could make use of it?).

I understand that this is bad code, and it would potentially be silly to implement a new feature to fix code that is bad in the first place, but I can't help but wonder if I'm the only one that truly needs this? A simple SDL_PeepEvents search with SDL_GETEVENT will show that it's used quite often (http://code.ohloh.net/search?s=sdl_peepevents%20get_event&pp=0&fl=C%2B%2B&fe=cpp&ff=1&mp=1&ml=1&me=1&md=1&filterChecked=true).

What do you think?
Title: Re: Clear Keyboard Events in buffer
Post by: zsbzsb on October 07, 2013, 06:44:10 pm
So why don't you implement your own event buffer. Have a std::vector<Event> for your event buffer. When you poll events then push all events into the vector. Then when a key press event happens do your database check. Then as soon as your database check returns handle all events that have happened since your thread blocked doing the database operation. After the backlog of events (occurred during DB operation) has been put into your buffer go through and clear the buffer of all key press events.

Something like this

This approach should ensure you are handling only 1 key press event at a time.
Title: Re: Clear Keyboard Events in buffer
Post by: Caeous on October 07, 2013, 07:58:46 pm
Thanks everyone for your input and help (Laurent, zsbzsb, binary1248). It's greatly appreciated. I've decided to go ahead and simply:
while( window.pollEvent( _event ) );

If the user continues to press a key or moving the mouse, well then it's his problem. In reality, after testing, the pollevent is faster than the key repeat, so it technically works for 99%, there's just this one edge case where if the mouse is constantly moving, then my app blocks until it stops. Odds of that happening in reality are low so I'm willing to compromise.

I'd rather not make you guys bloat the library with another function that only us legacy-stuck dudes are going to need.

Cheers and keep up the good work on SFML.