Skip to content

Commit f20fac9

Browse files
committed
Add platform::desktop module with EventLoopExt::run_return
1 parent dad24d0 commit f20fac9

File tree

4 files changed

+114
-34
lines changed

4 files changed

+114
-34
lines changed

examples/run_return.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
extern crate winit;
2+
use winit::platform::desktop::EventLoopExtDesktop;
3+
4+
fn main() {
5+
let mut events_loop = winit::EventLoop::new();
6+
7+
let window = winit::WindowBuilder::new()
8+
.with_title("A fantastic window!")
9+
.build(&events_loop)
10+
.unwrap();
11+
12+
println!("Close the window to continue.");
13+
events_loop.run_return(|event, _, control_flow| {
14+
match event {
15+
winit::Event::WindowEvent {
16+
event: winit::WindowEvent::CloseRequested,
17+
..
18+
} => *control_flow = winit::ControlFlow::Exit,
19+
_ => *control_flow = winit::ControlFlow::Wait,
20+
}
21+
});
22+
drop(window);
23+
24+
let _window_2 = winit::WindowBuilder::new()
25+
.with_title("A second, fantasticer window!")
26+
.build(&events_loop)
27+
.unwrap();
28+
29+
println!("Wa ha ha! You thought that closing the window would finish this?!");
30+
events_loop.run_return(|event, _, control_flow| {
31+
match event {
32+
winit::Event::WindowEvent {
33+
event: winit::WindowEvent::CloseRequested,
34+
..
35+
} => *control_flow = winit::ControlFlow::Exit,
36+
_ => *control_flow = winit::ControlFlow::Wait,
37+
}
38+
});
39+
40+
println!("Okay we're done now for real.");
41+
}

src/platform/desktop.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![cfg(any(
2+
target_os = "windows",
3+
target_os = "macos",
4+
target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"
5+
))]
6+
7+
use {EventLoop, Event, ControlFlow};
8+
9+
/// Additional methods on `EventLoop` that are specific to desktop platforms.
10+
pub trait EventLoopExtDesktop {
11+
type UserEvent;
12+
/// Initializes the `winit` event loop.
13+
///
14+
/// Unlikes `run`, this function *does* return control flow to the caller when `control_flow`
15+
/// is set to `ControlFlow::Exit`.
16+
fn run_return<F>(&mut self, event_handler: F)
17+
where F: FnMut(Event<Self::UserEvent>, &EventLoop<Self::UserEvent>, &mut ControlFlow);
18+
}
19+
20+
impl<T> EventLoopExtDesktop for EventLoop<T> {
21+
type UserEvent = T;
22+
23+
fn run_return<F>(&mut self, event_handler: F)
24+
where F: FnMut(Event<T>, &EventLoop<T>, &mut ControlFlow)
25+
{
26+
self.events_loop.run_return(event_handler)
27+
}
28+
}

src/platform/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ pub mod ios;
1515
pub mod macos;
1616
pub mod unix;
1717
pub mod windows;
18+
19+
pub mod desktop;

src/platform_impl/windows/events_loop.rs

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -182,35 +182,44 @@ impl<T> EventLoop<T> {
182182
}
183183
}
184184

185-
pub fn run<F>(self, mut event_handler: F) -> !
185+
pub fn run<F>(mut self, event_handler: F) -> !
186186
where F: 'static + FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow)
187187
{
188-
unsafe {
189-
winuser::IsGUIThread(1);
188+
self.run_return(event_handler);
189+
::std::process::exit(0);
190+
}
190191

191-
let mut runner = EventLoopRunner {
192-
event_loop: ::EventLoop {
193-
events_loop: self,
194-
_marker: ::std::marker::PhantomData
195-
},
196-
control_flow: ControlFlow::default(),
197-
runner_state: RunnerState::New,
198-
modal_loop_data: None,
199-
event_handler: &mut event_handler
200-
};
201-
{
202-
let runner_shared = runner.event_loop.events_loop.runner_shared.clone();
203-
let mut runner_shared = runner_shared.borrow_mut();
204-
let mut event_buffer = vec![];
205-
if let ELRSharedOption::Buffer(ref mut buffer) = *runner_shared {
206-
mem::swap(buffer, &mut event_buffer);
207-
}
208-
for event in event_buffer.drain(..) {
209-
runner.process_event(event);
210-
}
211-
*runner_shared = ELRSharedOption::Runner(&mut runner);
192+
pub fn run_return<F>(&mut self, mut event_handler: F)
193+
where F: FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow)
194+
{
195+
unsafe{ winuser::IsGUIThread(1); }
196+
let mut runner = EventLoopRunner {
197+
event_loop: self,
198+
control_flow: ControlFlow::default(),
199+
runner_state: RunnerState::New,
200+
modal_loop_data: None,
201+
event_handler: unsafe {
202+
// Transmute used to erase lifetimes.
203+
mem::transmute::<
204+
&mut FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow),
205+
*mut FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow)
206+
>(&mut event_handler)
212207
}
208+
};
209+
{
210+
let runner_shared = self.runner_shared.clone();
211+
let mut runner_shared = runner_shared.borrow_mut();
212+
let mut event_buffer = vec![];
213+
if let ELRSharedOption::Buffer(ref mut buffer) = *runner_shared {
214+
mem::swap(buffer, &mut event_buffer);
215+
}
216+
for event in event_buffer.drain(..) {
217+
unsafe{ runner.process_event(event); }
218+
}
219+
*runner_shared = ELRSharedOption::Runner(&mut runner);
220+
}
213221

222+
unsafe {
214223
let timer_handle = winuser::SetTimer(ptr::null_mut(), 0, 0x7FFFFFFF, None);
215224

216225
let mut msg = mem::uninitialized();
@@ -253,13 +262,10 @@ impl<T> EventLoop<T> {
253262
ControlFlow::Poll => ()
254263
}
255264
}
256-
257-
runner.call_event_handler(Event::LoopDestroyed);
258-
*runner.event_loop.events_loop.runner_shared.borrow_mut() = ELRSharedOption::Buffer(vec![]);
259265
}
260266

261-
drop(event_handler);
262-
::std::process::exit(0);
267+
unsafe{ runner.call_event_handler(Event::LoopDestroyed) }
268+
*self.runner_shared.borrow_mut() = ELRSharedOption::Buffer(vec![]);
263269
}
264270

265271
pub fn create_proxy(&self) -> EventLoopProxy<T> {
@@ -284,7 +290,7 @@ pub(crate) enum ELRSharedOption<T> {
284290
Buffer(Vec<Event<T>>)
285291
}
286292
pub(crate) struct EventLoopRunner<T> {
287-
event_loop: ::EventLoop<T>,
293+
event_loop: *const EventLoop<T>,
288294
control_flow: ControlFlow,
289295
runner_state: RunnerState,
290296
modal_loop_data: Option<ModalLoopData>,
@@ -457,15 +463,18 @@ impl<T> EventLoopRunner<T> {
457463
unsafe fn call_event_handler(&mut self, event: Event<T>) {
458464
if self.event_handler != mem::zeroed() {
459465
match event {
460-
Event::NewEvents(_) => self.event_loop.events_loop.trigger_newevents_on_redraw.store(true, Ordering::Relaxed),
461-
Event::EventsCleared => self.event_loop.events_loop.trigger_newevents_on_redraw.store(false, Ordering::Relaxed),
466+
Event::NewEvents(_) => (*self.event_loop).trigger_newevents_on_redraw.store(true, Ordering::Relaxed),
467+
Event::EventsCleared => (*self.event_loop).trigger_newevents_on_redraw.store(false, Ordering::Relaxed),
462468
_ => ()
463469
}
464470

471+
assert_eq!(mem::size_of::<::EventLoop<T>>(), mem::size_of::<EventLoop<T>>());
472+
let event_loop_ref = &*(self.event_loop as *const ::EventLoop<T>);
473+
465474
if self.control_flow != ControlFlow::Exit {
466-
(*self.event_handler)(event, &self.event_loop, &mut self.control_flow);
475+
(*self.event_handler)(event, event_loop_ref, &mut self.control_flow);
467476
} else {
468-
(*self.event_handler)(event, &self.event_loop, &mut ControlFlow::Exit);
477+
(*self.event_handler)(event, event_loop_ref, &mut ControlFlow::Exit);
469478
}
470479
} else {
471480
panic!("Tried to call event handler with null handler");

0 commit comments

Comments
 (0)