Crates.io | async-winit |
lib.rs | async-winit |
version | 0.2.1 |
source | src |
created_at | 2023-04-16 22:33:41.093671 |
updated_at | 2023-10-15 00:50:04.839714 |
description | Use winit like an async runtime |
homepage | |
repository | https://github.com/notgull/async-winit |
max_upload_size | |
id | 840959 |
size | 289,038 |
Use winit
like the async
runtime you've always wanted.
winit
is actually asynchronous, contrary to popular belief; it's just not async
. It uses an event loop to handle events, which is an good fit for some cases but not others. The maintainers of winit
have referred to this type of event loop as "poor man's async
"; a system that is not async
but is still asynchronous.
This crate builds an async
interface on top of this event loop.
Consider the following winit
program, which creates a window and prints the size of the window when it is resized:
use winit::event::{Event, WindowEvent};
use winit::event_loop::EventLoop;
use winit::window::Window;
fn main2(evl: EventLoop<()>) {
let mut window = None;
evl.run(move |event, elwt, flow| {
match event {
Event::Resumed => {
// Application is active; create a window.
window = Some(Window::new(elwt).unwrap());
},
Event::Suspended => {
// Application is inactive; destroy the window.
window = None;
},
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => {
// Window is closed; exit the application.
flow.set_exit();
},
WindowEvent::Resized(size) => {
println!("{:?}", size);
}
_ => {},
},
_ => {},
}
});
}
fn main() {
# return;
let evl = EventLoop::new();
main2(evl);
}
This strategy is a bit long winded. Now, compare against the equivalent async-winit
program:
use async_winit::event_loop::EventLoop;
use async_winit::window::Window;
use async_winit::ThreadUnsafe;
use futures_lite::prelude::*;
fn main2(evl: EventLoop<ThreadUnsafe>) {
let window_target = evl.window_target().clone();
evl.block_on(async move {
loop {
// Wait for the application to be active.
window_target.resumed().await;
// Create a window.
let window = Window::<ThreadUnsafe>::new().await.unwrap();
// Print the size of the window when it is resized.
let print_size = async {
window
.resized()
.wait()
.for_each(|size| {
println!("{:?}", size);
})
.await;
true
};
// Wait until the window is closed.
let close = async {
window.close_requested().wait().await;
println!("Close");
true
};
// Wait until the application is suspended.
let suspend = async {
window_target.suspended().wait().await;
false
};
// Run all of these at once.
let needs_exit = print_size.or(close).or(suspend).await;
// If we need to exit, exit. Otherwise, loop again, destroying the window.
if needs_exit {
window_target.exit().await;
} else {
drop(window);
}
}
});
}
fn main() {
# return;
let evl = EventLoop::new();
main2(evl);
}
In my opinion, the flatter async
style is much easier to read and understand. Your mileage may vary.
async
task, rather than an event loop.EventLoopWindowTarget
; Window::new()
and other functions take no parameters and can be called from anywhere as long as an EventLoop
is running somewhere.async
ecosystem to its full potential here.async-winit
. This is because async-winit
is built on top of winit
, which is built on top of winit
's event loop. This means that async-winit
has to convert between async
and winit
's event loop, which is not free.async-winit
is not as low level as winit
. This means that you can't do everything that you can do with winit
.
RefCell
in simple cases, but still requires additional thought for shared state.async-winit
was created by John Nunley (@notgull).
This project is heavily based on async-io
by Stjepan Glavina et al, as well as winit
by Pierre Kreiger et al.
async-winit
is free software: you can redistribute it and/or modify it under the terms of one of the following licenses:
async-winit
is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the Mozilla Public License for more details.
You should have received a copy of the GNU Lesser General Public License and the Mozilla Public License along with async-winit
. If not, see https://www.gnu.org/licenses/.