Event Loop
Takeaways:
- An event loop is a loop that polls for an event.
- When an event is received, some code is run. The code is the
event_handler
. - The application provides the
event_handler
. - Native: The application controls the event loop –
winit
. - WASM: The browser controls the event loop, but consistent API is still exposed by
winit
. - Github issue(s): amethyst#2191
Event loop example
winit
:
// Not real code
impl EventLoop {
pub fn run<F>(self, event_handler: F) -> !
where
F: ..
{
loop {
let event = poll_event(); // Blocks until an event arrives.
event_handler(event, ..);
}
}
}
amethyst
:
// Not real code, but close 🤏.
let event_handler = move |event, _, control_flow| {
match event {
// tick the game
Event::MainEventsCleared => self.run_game_logic(),
// input
Event::DeviceEvent(device_event) => self.notify_input(device_event),
_ => {},
}
};
event_loop.run(event_handler);
// Never reached, as EventLoop::run(_) returns `!`.
loop {
let event = poll_event(); // Blocks until an event arrives.
event_handler(event, ..);
}
Native
In a native application, the event loop receives events from the operating system.
WASM
In a browser, the event loop is not controlled by winit
, but the browser.
To surrender control to the browser, winit
sends the event handler to the browser, and panics.
The Window::requestAnimationFrame
API is used to receive events.
Javascript callback example
// While `pixel_shift`` is less than 100, call `requestAnimationFrame`.
var pixel_shift = 0;
function move(_timestamp) {
element.style.transform = 'translateX(' + pixel_shift + 'px)';
if (pixel_shift < 100) {
pixel_shift += 1;
window.requestAnimationFrame(move);
}
}
window.requestAnimationFrame(move);
To ensure requestAnimationFrame
is called, in the event handler, the control_flow
parameter must be set to ControlFlow::Poll
.
let event_handler = move |event, _, control_flow| {
// ..
// Ensure the browser calls `requestAnimationFrame`
// This will ensure this event handler is run, even if no events arrive.
*control_flow = ControlFlow::Poll;
};
event_loop.run(event_handler);