In a program that uses poll_events in an infinite loop, poll_events will process events until the event queue is empty. If multiple events are enqueued while the program is rendering, the program can process each of them before beginning the relatively expensive task of rendering the next frame.
With run_forever though, this sort of "bulk event processing" cannot happen. The callback does not know if more events are in the queue, so it must unconditionally render a frame to the user. But while rendering a frame, more events can be enqueued. If rendering takes too long, the input queue becomes filled with events, and the run_forever callback cannot process them fast enough as it has to process older events first.
This severely affects interactivity; the program appears to the user that the program is constantly "catching up" with what the user did seconds ago (this is particularly noticeable when moving the mouse, which causes many events).
There are a couple workarounds to this issue. The obvious one is to use poll_events instead. However, if the program only needs to re-render in response to user input (common in editors), rendering all of the time wastes CPU and power.
A more complicated workaround is to have the event loop forward all of its events to the program's own queue (such as std::sync::mpsc), which can implement a "check if empty function". This introduces complexity in the program, though, and it would be better if winit had a simpler interface.
The API described in #231 would solve this issue. The program can call get_event with a short timeout until no events are left, then render the frame and call get_event with an infinite timeout.
In a program that uses
poll_eventsin an infinite loop,poll_eventswill process events until the event queue is empty. If multiple events are enqueued while the program is rendering, the program can process each of them before beginning the relatively expensive task of rendering the next frame.With
run_foreverthough, this sort of "bulk event processing" cannot happen. The callback does not know if more events are in the queue, so it must unconditionally render a frame to the user. But while rendering a frame, more events can be enqueued. If rendering takes too long, the input queue becomes filled with events, and therun_forevercallback cannot process them fast enough as it has to process older events first.This severely affects interactivity; the program appears to the user that the program is constantly "catching up" with what the user did seconds ago (this is particularly noticeable when moving the mouse, which causes many events).
There are a couple workarounds to this issue. The obvious one is to use
poll_eventsinstead. However, if the program only needs to re-render in response to user input (common in editors), rendering all of the time wastes CPU and power.A more complicated workaround is to have the event loop forward all of its events to the program's own queue (such as
std::sync::mpsc), which can implement a "check if empty function". This introduces complexity in the program, though, and it would be better ifwinithad a simpler interface.The API described in #231 would solve this issue. The program can call
get_eventwith a short timeout until no events are left, then render the frame and callget_eventwith an infinite timeout.