mirror of
https://github.com/rust-windowing/winit.git
synced 2026-08-29 04:40:04 -04:00
Add platform::desktop module with EventLoopExt::run_return
This commit is contained in:
41
examples/run_return.rs
Normal file
41
examples/run_return.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
extern crate winit;
|
||||||
|
use winit::platform::desktop::EventLoopExtDesktop;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut events_loop = winit::EventLoop::new();
|
||||||
|
|
||||||
|
let window = winit::WindowBuilder::new()
|
||||||
|
.with_title("A fantastic window!")
|
||||||
|
.build(&events_loop)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!("Close the window to continue.");
|
||||||
|
events_loop.run_return(|event, _, control_flow| {
|
||||||
|
match event {
|
||||||
|
winit::Event::WindowEvent {
|
||||||
|
event: winit::WindowEvent::CloseRequested,
|
||||||
|
..
|
||||||
|
} => *control_flow = winit::ControlFlow::Exit,
|
||||||
|
_ => *control_flow = winit::ControlFlow::Wait,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
drop(window);
|
||||||
|
|
||||||
|
let _window_2 = winit::WindowBuilder::new()
|
||||||
|
.with_title("A second, fantasticer window!")
|
||||||
|
.build(&events_loop)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!("Wa ha ha! You thought that closing the window would finish this?!");
|
||||||
|
events_loop.run_return(|event, _, control_flow| {
|
||||||
|
match event {
|
||||||
|
winit::Event::WindowEvent {
|
||||||
|
event: winit::WindowEvent::CloseRequested,
|
||||||
|
..
|
||||||
|
} => *control_flow = winit::ControlFlow::Exit,
|
||||||
|
_ => *control_flow = winit::ControlFlow::Wait,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
println!("Okay we're done now for real.");
|
||||||
|
}
|
||||||
28
src/platform/desktop.rs
Normal file
28
src/platform/desktop.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#![cfg(any(
|
||||||
|
target_os = "windows",
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"
|
||||||
|
))]
|
||||||
|
|
||||||
|
use {EventLoop, Event, ControlFlow};
|
||||||
|
|
||||||
|
/// Additional methods on `EventLoop` that are specific to desktop platforms.
|
||||||
|
pub trait EventLoopExtDesktop {
|
||||||
|
type UserEvent;
|
||||||
|
/// Initializes the `winit` event loop.
|
||||||
|
///
|
||||||
|
/// Unlikes `run`, this function *does* return control flow to the caller when `control_flow`
|
||||||
|
/// is set to `ControlFlow::Exit`.
|
||||||
|
fn run_return<F>(&mut self, event_handler: F)
|
||||||
|
where F: FnMut(Event<Self::UserEvent>, &EventLoop<Self::UserEvent>, &mut ControlFlow);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> EventLoopExtDesktop for EventLoop<T> {
|
||||||
|
type UserEvent = T;
|
||||||
|
|
||||||
|
fn run_return<F>(&mut self, event_handler: F)
|
||||||
|
where F: FnMut(Event<T>, &EventLoop<T>, &mut ControlFlow)
|
||||||
|
{
|
||||||
|
self.events_loop.run_return(event_handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,3 +15,5 @@ pub mod ios;
|
|||||||
pub mod macos;
|
pub mod macos;
|
||||||
pub mod unix;
|
pub mod unix;
|
||||||
pub mod windows;
|
pub mod windows;
|
||||||
|
|
||||||
|
pub mod desktop;
|
||||||
|
|||||||
@@ -182,35 +182,44 @@ impl<T> EventLoop<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run<F>(self, mut event_handler: F) -> !
|
pub fn run<F>(mut self, event_handler: F) -> !
|
||||||
where F: 'static + FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow)
|
where F: 'static + FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow)
|
||||||
{
|
{
|
||||||
unsafe {
|
self.run_return(event_handler);
|
||||||
winuser::IsGUIThread(1);
|
::std::process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
let mut runner = EventLoopRunner {
|
pub fn run_return<F>(&mut self, mut event_handler: F)
|
||||||
event_loop: ::EventLoop {
|
where F: FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow)
|
||||||
events_loop: self,
|
{
|
||||||
_marker: ::std::marker::PhantomData
|
unsafe{ winuser::IsGUIThread(1); }
|
||||||
},
|
let mut runner = EventLoopRunner {
|
||||||
control_flow: ControlFlow::default(),
|
event_loop: self,
|
||||||
runner_state: RunnerState::New,
|
control_flow: ControlFlow::default(),
|
||||||
modal_loop_data: None,
|
runner_state: RunnerState::New,
|
||||||
event_handler: &mut event_handler
|
modal_loop_data: None,
|
||||||
};
|
event_handler: unsafe {
|
||||||
{
|
// Transmute used to erase lifetimes.
|
||||||
let runner_shared = runner.event_loop.events_loop.runner_shared.clone();
|
mem::transmute::<
|
||||||
let mut runner_shared = runner_shared.borrow_mut();
|
&mut FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow),
|
||||||
let mut event_buffer = vec![];
|
*mut FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow)
|
||||||
if let ELRSharedOption::Buffer(ref mut buffer) = *runner_shared {
|
>(&mut event_handler)
|
||||||
mem::swap(buffer, &mut event_buffer);
|
|
||||||
}
|
|
||||||
for event in event_buffer.drain(..) {
|
|
||||||
runner.process_event(event);
|
|
||||||
}
|
|
||||||
*runner_shared = ELRSharedOption::Runner(&mut runner);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
{
|
||||||
|
let runner_shared = self.runner_shared.clone();
|
||||||
|
let mut runner_shared = runner_shared.borrow_mut();
|
||||||
|
let mut event_buffer = vec![];
|
||||||
|
if let ELRSharedOption::Buffer(ref mut buffer) = *runner_shared {
|
||||||
|
mem::swap(buffer, &mut event_buffer);
|
||||||
|
}
|
||||||
|
for event in event_buffer.drain(..) {
|
||||||
|
unsafe{ runner.process_event(event); }
|
||||||
|
}
|
||||||
|
*runner_shared = ELRSharedOption::Runner(&mut runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
let timer_handle = winuser::SetTimer(ptr::null_mut(), 0, 0x7FFFFFFF, None);
|
let timer_handle = winuser::SetTimer(ptr::null_mut(), 0, 0x7FFFFFFF, None);
|
||||||
|
|
||||||
let mut msg = mem::uninitialized();
|
let mut msg = mem::uninitialized();
|
||||||
@@ -253,13 +262,10 @@ impl<T> EventLoop<T> {
|
|||||||
ControlFlow::Poll => ()
|
ControlFlow::Poll => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runner.call_event_handler(Event::LoopDestroyed);
|
|
||||||
*runner.event_loop.events_loop.runner_shared.borrow_mut() = ELRSharedOption::Buffer(vec![]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(event_handler);
|
unsafe{ runner.call_event_handler(Event::LoopDestroyed) }
|
||||||
::std::process::exit(0);
|
*self.runner_shared.borrow_mut() = ELRSharedOption::Buffer(vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
||||||
@@ -284,7 +290,7 @@ pub(crate) enum ELRSharedOption<T> {
|
|||||||
Buffer(Vec<Event<T>>)
|
Buffer(Vec<Event<T>>)
|
||||||
}
|
}
|
||||||
pub(crate) struct EventLoopRunner<T> {
|
pub(crate) struct EventLoopRunner<T> {
|
||||||
event_loop: ::EventLoop<T>,
|
event_loop: *const EventLoop<T>,
|
||||||
control_flow: ControlFlow,
|
control_flow: ControlFlow,
|
||||||
runner_state: RunnerState,
|
runner_state: RunnerState,
|
||||||
modal_loop_data: Option<ModalLoopData>,
|
modal_loop_data: Option<ModalLoopData>,
|
||||||
@@ -457,15 +463,18 @@ impl<T> EventLoopRunner<T> {
|
|||||||
unsafe fn call_event_handler(&mut self, event: Event<T>) {
|
unsafe fn call_event_handler(&mut self, event: Event<T>) {
|
||||||
if self.event_handler != mem::zeroed() {
|
if self.event_handler != mem::zeroed() {
|
||||||
match event {
|
match event {
|
||||||
Event::NewEvents(_) => self.event_loop.events_loop.trigger_newevents_on_redraw.store(true, Ordering::Relaxed),
|
Event::NewEvents(_) => (*self.event_loop).trigger_newevents_on_redraw.store(true, Ordering::Relaxed),
|
||||||
Event::EventsCleared => self.event_loop.events_loop.trigger_newevents_on_redraw.store(false, Ordering::Relaxed),
|
Event::EventsCleared => (*self.event_loop).trigger_newevents_on_redraw.store(false, Ordering::Relaxed),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_eq!(mem::size_of::<::EventLoop<T>>(), mem::size_of::<EventLoop<T>>());
|
||||||
|
let event_loop_ref = &*(self.event_loop as *const ::EventLoop<T>);
|
||||||
|
|
||||||
if self.control_flow != ControlFlow::Exit {
|
if self.control_flow != ControlFlow::Exit {
|
||||||
(*self.event_handler)(event, &self.event_loop, &mut self.control_flow);
|
(*self.event_handler)(event, event_loop_ref, &mut self.control_flow);
|
||||||
} else {
|
} else {
|
||||||
(*self.event_handler)(event, &self.event_loop, &mut ControlFlow::Exit);
|
(*self.event_handler)(event, event_loop_ref, &mut ControlFlow::Exit);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("Tried to call event handler with null handler");
|
panic!("Tried to call event handler with null handler");
|
||||||
|
|||||||
Reference in New Issue
Block a user