Skip to content

RFC: Switch to a futures-compatible API #20

@tomaka

Description

@tomaka

Winit's and glutin's current API look like this:

impl Window {
    pub fn wait_events(&self) -> impl Iterator<Item = Event> { ... }
    pub fn poll_events(&self) -> impl Iterator<Item = Event> { ... }
}

I suggest that instead you'd have to register your window to what's called an events loop. Then, you'd call a method on the events loop to run it. Running the events loop would process events received by the operating system, and call a callback previously registered on the window.

This is essentially the same approach as the future-rs library, except that we're not using future-rs directly because it's not totally stable. I'd like to eventually publish winit 1.0 (in, like, the next nine months or so), and it's unlikely that future-rs publishes its 1.0 before winit.

Example usage with the new API (just to give an overview, the details are not important at the moment):

let events_loop = EventsLoop::new();
let window = WindowBuilder::new().with_title("hello").build(&events_loop).unwrap();
window.set_callback(|event| match event { ... });

loop {
    events_loop.run_once();     // calls the closure passed to set_callback earlier
}

I've always been a bit wary about callbacks because they are often too "magical", like you don't know which thread calls them and at what moment. But the fact that it's the run() method of the events loop that calls the callbacks means that it's a good design in my opinion.

This approach would have some benefits over the current system:

  • In the implementation we can decouple the Window object in Rust from the actual window. The actual window could be stored in the EventsLoop for example.
  • Right now on Windows winit spawns a background thread for events handling ; this could be removed.
  • We can force the EventsLoop to run on the main thread for OSX while still allowing the Window objects to be shared between threads. This has been a huge safety hole in glutin since the beginning.
  • The set_resize_callback function of MacOS would be gone.
  • The WindowProxy would be gone in favor of an "EventsLoopProxy".
  • We can later register other kinds of callbacks to the events loop, for example a callback when a monitoring is plugged in or removed that is not tied to particular window.
  • This design is also more appropriate for emscripten in glutin, as emscripten/javascript are based on callbacks and not on preemptive multitasking.

Metadata

Metadata

Assignees

No one assigned

    Labels

    S - apiDesign and usability

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions