Crates.io | winit-main |
lib.rs | winit-main |
version | 0.1.3 |
source | src |
created_at | 2021-01-11 03:45:01.831219 |
updated_at | 2021-11-29 06:43:34.959823 |
description | Abstract away winit's event-loop inversion of control |
homepage | |
repository | https://gitlab.com/gretchenfrage/winit-main |
max_upload_size | |
id | 340073 |
size | 50,622 |
This is a winit
utility which abstracts away
winit's event-loop inversion of control.
Winit necessarily hijacks the main thread due to platform constraints, creating a "don't call us, we'll call you" situation. Inversions of control have some undesirable properties, including:
This library spawns your code on a second thread (a "simulated main thread"), hijacks the real main thread with winit's event loop, and provides your code handles to communicate with the main event loop. This allows you to write your program as you would any other program, treating winit's event loop as an iterator of events and a handle with which to create windows and ask about the system. When the simulated main thread exits, it triggers the event loop to exit, shutting down the process, just like if it were the real main thread.
The simulated main thread receives winit Event
s through an EventReceiver
.
In these events, the user event type is a Blocker
. This is a concurrency
structure emitted by the main thread which blocks the event loop from
processing further winit events until the Blocker
is dropped. This is a way
to synchronize the event loop with the simulated main thread to some extent,
such as to synchronize the presenting of images.
Whenever the event loop encounters a RedrawRequested
event, it immediately
emits a Blocker
, and thus will not proceed until the simulated main thread
receives and drops that Blocker
.
ControlFlow
This library keeps the winit event loop in the ControlFlow::Wait
state.
Therefore, if you want to redraw a window in a loop, you should call
Window::request_redraw
after every draw.
winit-main
:use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
if matches!(
event,
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id()
) {
*control_flow = ControlFlow::Exit;
}
});
}
winit-main
(no proc macro):use winit_main::reexports::{
event::{Event, WindowEvent},
window::WindowAttributes,
};
fn main() {
winit_main::run(|event_loop, events| {
let window = event_loop
.create_window(WindowAttributes::default())
.unwrap();
for event in events.iter() {
if matches!(
event,
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id()
) {
break;
}
}
});
}
winit-main
(with proc macro):use winit_main::{
reexports::{
event::{Event, WindowEvent},
window::WindowAttributes,
},
EventLoopHandle,
EventReceiver,
};
#[winit_main::main]
fn main(event_loop: EventLoopHandle, events: EventReceiver) {
let window = event_loop
.create_window(WindowAttributes::default())
.unwrap();
for event in events.iter() {
if matches!(
event,
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id()
) {
break;
}
}
}
This project is young, barely tested, and probably poorly optimized. The main
form of test is the wgpu-example
package in this repository, which is the
triangle example from the wgpu
project, modified to utilize this abstraction.