parent
8fdd81ecef
commit
e648169861
60 changed files with 800 additions and 860 deletions
|
|
@ -250,14 +250,14 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
pub fn run<F>(mut self, event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
|
||||
F: FnMut(Event<T>, &RootELW<T>),
|
||||
{
|
||||
self.run_ondemand(event_handler)
|
||||
}
|
||||
|
||||
pub fn run_ondemand<F>(&mut self, mut event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
|
||||
F: FnMut(Event<T>, &RootELW<T>),
|
||||
{
|
||||
{
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
|
|
@ -270,18 +270,20 @@ impl<T: 'static> EventLoop<T> {
|
|||
// We make sure to call runner.clear_event_handler() before
|
||||
// returning
|
||||
unsafe {
|
||||
runner.set_event_handler(move |event, control_flow| {
|
||||
event_handler(event, event_loop_windows_ref, control_flow)
|
||||
});
|
||||
runner.set_event_handler(move |event| event_handler(event, event_loop_windows_ref));
|
||||
}
|
||||
}
|
||||
|
||||
let exit_code = loop {
|
||||
if let ControlFlow::ExitWithCode(code) = self.wait_and_dispatch_message(None) {
|
||||
self.wait_and_dispatch_message(None);
|
||||
|
||||
if let Some(code) = self.exit_code() {
|
||||
break code;
|
||||
}
|
||||
|
||||
if let ControlFlow::ExitWithCode(code) = self.dispatch_peeked_messages() {
|
||||
self.dispatch_peeked_messages();
|
||||
|
||||
if let Some(code) = self.exit_code() {
|
||||
break code;
|
||||
}
|
||||
};
|
||||
|
|
@ -303,7 +305,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
pub fn pump_events<F>(&mut self, timeout: Option<Duration>, mut event_handler: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
|
||||
F: FnMut(Event<T>, &RootELW<T>),
|
||||
{
|
||||
{
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
|
|
@ -317,23 +319,20 @@ impl<T: 'static> EventLoop<T> {
|
|||
// to leave the runner in an unsound state with an associated
|
||||
// event handler.
|
||||
unsafe {
|
||||
runner.set_event_handler(move |event, control_flow| {
|
||||
event_handler(event, event_loop_windows_ref, control_flow)
|
||||
});
|
||||
runner.set_event_handler(move |event| event_handler(event, event_loop_windows_ref));
|
||||
runner.wakeup();
|
||||
}
|
||||
}
|
||||
|
||||
if !matches!(
|
||||
self.wait_and_dispatch_message(timeout),
|
||||
ControlFlow::ExitWithCode(_)
|
||||
) {
|
||||
self.wait_and_dispatch_message(timeout);
|
||||
|
||||
if self.exit_code().is_none() {
|
||||
self.dispatch_peeked_messages();
|
||||
}
|
||||
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
|
||||
let status = if let ControlFlow::ExitWithCode(code) = runner.control_flow() {
|
||||
let status = if let Some(code) = runner.exit_code() {
|
||||
runner.loop_destroyed();
|
||||
|
||||
// Immediately reset the internal state for the loop to allow
|
||||
|
|
@ -357,7 +356,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
|
||||
/// Wait for one message and dispatch it, optionally with a timeout
|
||||
fn wait_and_dispatch_message(&mut self, timeout: Option<Duration>) -> ControlFlow {
|
||||
fn wait_and_dispatch_message(&mut self, timeout: Option<Duration>) {
|
||||
let start = Instant::now();
|
||||
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
|
|
@ -368,7 +367,6 @@ impl<T: 'static> EventLoop<T> {
|
|||
ControlFlow::WaitUntil(wait_deadline) => {
|
||||
Some(wait_deadline.saturating_duration_since(start))
|
||||
}
|
||||
ControlFlow::ExitWithCode(_code) => unreachable!(),
|
||||
};
|
||||
let timeout = min_timeout(control_flow_timeout, timeout);
|
||||
|
||||
|
|
@ -432,8 +430,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
match msg_status {
|
||||
None => {} // No MSG to dispatch
|
||||
Some(PumpStatus::Exit(code)) => {
|
||||
runner.set_exit_control_flow(code);
|
||||
return runner.control_flow();
|
||||
runner.set_exit_code(code);
|
||||
}
|
||||
Some(PumpStatus::Continue) => {
|
||||
unsafe {
|
||||
|
|
@ -454,12 +451,10 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
runner.control_flow()
|
||||
}
|
||||
|
||||
/// Dispatch all queued messages via `PeekMessageW`
|
||||
fn dispatch_peeked_messages(&mut self) -> ControlFlow {
|
||||
fn dispatch_peeked_messages(&mut self) {
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
|
||||
// We generally want to continue dispatching all pending messages
|
||||
|
|
@ -476,8 +471,6 @@ impl<T: 'static> EventLoop<T> {
|
|||
// is the simplest way avoid unitialized memory in Rust
|
||||
let mut msg = unsafe { mem::zeroed() };
|
||||
|
||||
let mut control_flow = runner.control_flow();
|
||||
|
||||
loop {
|
||||
unsafe {
|
||||
if PeekMessageW(&mut msg, 0, 0, 0, PM_REMOVE) == false.into() {
|
||||
|
|
@ -500,8 +493,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
panic::resume_unwind(payload);
|
||||
}
|
||||
|
||||
control_flow = runner.control_flow();
|
||||
if let ControlFlow::ExitWithCode(_code) = control_flow {
|
||||
if let Some(_code) = runner.exit_code() {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -509,8 +501,6 @@ impl<T: 'static> EventLoop<T> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
control_flow
|
||||
}
|
||||
|
||||
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
||||
|
|
@ -519,6 +509,10 @@ impl<T: 'static> EventLoop<T> {
|
|||
event_send: self.thread_msg_sender.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn exit_code(&self) -> Option<i32> {
|
||||
self.window_target.p.exit_code()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> EventLoopWindowTarget<T> {
|
||||
|
|
@ -547,6 +541,26 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
pub fn listen_device_events(&self, allowed: DeviceEvents) {
|
||||
raw_input::register_all_mice_and_keyboards_for_raw_input(self.thread_msg_target, allowed);
|
||||
}
|
||||
|
||||
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
|
||||
self.runner_shared.set_control_flow(control_flow)
|
||||
}
|
||||
|
||||
pub(crate) fn control_flow(&self) -> ControlFlow {
|
||||
self.runner_shared.control_flow()
|
||||
}
|
||||
|
||||
pub(crate) fn exit(&self) {
|
||||
self.runner_shared.set_exit_code(0)
|
||||
}
|
||||
|
||||
pub(crate) fn exiting(&self) -> bool {
|
||||
self.runner_shared.exit_code().is_some()
|
||||
}
|
||||
|
||||
fn exit_code(&self) -> Option<i32> {
|
||||
self.runner_shared.exit_code()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the id of the main thread.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use windows_sys::Win32::Foundation::HWND;
|
|||
use crate::{
|
||||
dpi::PhysicalSize,
|
||||
event::{Event, InnerSizeWriter, StartCause, WindowEvent},
|
||||
event_loop::ControlFlow,
|
||||
platform_impl::platform::{
|
||||
event_loop::{WindowData, GWL_USERDATA},
|
||||
get_window_long,
|
||||
|
|
@ -21,9 +20,11 @@ use crate::{
|
|||
window::WindowId,
|
||||
};
|
||||
|
||||
use super::ControlFlow;
|
||||
|
||||
pub(crate) type EventLoopRunnerShared<T> = Rc<EventLoopRunner<T>>;
|
||||
|
||||
type EventHandler<T> = Cell<Option<Box<dyn FnMut(Event<T>, &mut ControlFlow)>>>;
|
||||
type EventHandler<T> = Cell<Option<Box<dyn FnMut(Event<T>)>>>;
|
||||
|
||||
pub(crate) struct EventLoopRunner<T: 'static> {
|
||||
// The event loop's win32 handles
|
||||
|
|
@ -35,6 +36,7 @@ pub(crate) struct EventLoopRunner<T: 'static> {
|
|||
pub(super) interrupt_msg_dispatch: Cell<bool>,
|
||||
|
||||
control_flow: Cell<ControlFlow>,
|
||||
exit: Cell<Option<i32>>,
|
||||
runner_state: Cell<RunnerState>,
|
||||
last_events_cleared: Cell<Instant>,
|
||||
event_handler: EventHandler<T>,
|
||||
|
|
@ -70,7 +72,8 @@ impl<T> EventLoopRunner<T> {
|
|||
thread_msg_target,
|
||||
interrupt_msg_dispatch: Cell::new(false),
|
||||
runner_state: Cell::new(RunnerState::Uninitialized),
|
||||
control_flow: Cell::new(ControlFlow::Poll),
|
||||
control_flow: Cell::new(ControlFlow::default()),
|
||||
exit: Cell::new(None),
|
||||
panic_error: Cell::new(None),
|
||||
last_events_cleared: Cell::new(Instant::now()),
|
||||
event_handler: Cell::new(None),
|
||||
|
|
@ -91,11 +94,11 @@ impl<T> EventLoopRunner<T> {
|
|||
/// undefined behaviour.
|
||||
pub(crate) unsafe fn set_event_handler<F>(&self, f: F)
|
||||
where
|
||||
F: FnMut(Event<T>, &mut ControlFlow),
|
||||
F: FnMut(Event<T>),
|
||||
{
|
||||
let old_event_handler = self.event_handler.replace(mem::transmute::<
|
||||
Option<Box<dyn FnMut(Event<T>, &mut ControlFlow)>>,
|
||||
Option<Box<dyn FnMut(Event<T>, &mut ControlFlow)>>,
|
||||
Option<Box<dyn FnMut(Event<T>)>>,
|
||||
Option<Box<dyn FnMut(Event<T>)>>,
|
||||
>(Some(Box::new(f))));
|
||||
assert!(old_event_handler.is_none());
|
||||
}
|
||||
|
|
@ -111,6 +114,7 @@ impl<T> EventLoopRunner<T> {
|
|||
runner_state,
|
||||
panic_error,
|
||||
control_flow,
|
||||
exit,
|
||||
last_events_cleared: _,
|
||||
event_handler,
|
||||
event_buffer: _,
|
||||
|
|
@ -118,7 +122,8 @@ impl<T> EventLoopRunner<T> {
|
|||
interrupt_msg_dispatch.set(false);
|
||||
runner_state.set(RunnerState::Uninitialized);
|
||||
panic_error.set(None);
|
||||
control_flow.set(ControlFlow::Poll);
|
||||
control_flow.set(ControlFlow::default());
|
||||
exit.set(None);
|
||||
event_handler.set(None);
|
||||
}
|
||||
}
|
||||
|
|
@ -141,14 +146,22 @@ impl<T> EventLoopRunner<T> {
|
|||
self.runner_state.get()
|
||||
}
|
||||
|
||||
pub fn set_exit_control_flow(&self, code: i32) {
|
||||
self.control_flow.set(ControlFlow::ExitWithCode(code))
|
||||
pub fn set_control_flow(&self, control_flow: ControlFlow) {
|
||||
self.control_flow.set(control_flow)
|
||||
}
|
||||
|
||||
pub fn control_flow(&self) -> ControlFlow {
|
||||
self.control_flow.get()
|
||||
}
|
||||
|
||||
pub fn set_exit_code(&self, code: i32) {
|
||||
self.exit.set(Some(code))
|
||||
}
|
||||
|
||||
pub fn exit_code(&self) -> Option<i32> {
|
||||
self.exit.get()
|
||||
}
|
||||
|
||||
pub fn should_buffer(&self) -> bool {
|
||||
let handler = self.event_handler.take();
|
||||
let should_buffer = handler.is_none();
|
||||
|
|
@ -226,18 +239,12 @@ impl<T> EventLoopRunner<T> {
|
|||
|
||||
fn call_event_handler(&self, event: Event<T>) {
|
||||
self.catch_unwind(|| {
|
||||
let mut control_flow = self.control_flow.take();
|
||||
let mut event_handler = self.event_handler.take()
|
||||
.expect("either event handler is re-entrant (likely), or no event handler is registered (very unlikely)");
|
||||
|
||||
if let ControlFlow::ExitWithCode(code) = control_flow {
|
||||
event_handler(event, &mut ControlFlow::ExitWithCode(code));
|
||||
} else {
|
||||
event_handler(event, &mut control_flow);
|
||||
}
|
||||
event_handler(event);
|
||||
|
||||
assert!(self.event_handler.replace(Some(event_handler)).is_none());
|
||||
self.control_flow.set(control_flow);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -332,16 +339,14 @@ impl<T> EventLoopRunner<T> {
|
|||
}
|
||||
|
||||
fn call_new_events(&self, init: bool) {
|
||||
let start_cause = match (init, self.control_flow()) {
|
||||
(true, _) => StartCause::Init,
|
||||
(false, ControlFlow::Poll) => StartCause::Poll,
|
||||
(false, ControlFlow::ExitWithCode(_)) | (false, ControlFlow::Wait) => {
|
||||
StartCause::WaitCancelled {
|
||||
requested_resume: None,
|
||||
start: self.last_events_cleared.get(),
|
||||
}
|
||||
}
|
||||
(false, ControlFlow::WaitUntil(requested_resume)) => {
|
||||
let start_cause = match (init, self.control_flow(), self.exit.get()) {
|
||||
(true, _, _) => StartCause::Init,
|
||||
(false, ControlFlow::Poll, None) => StartCause::Poll,
|
||||
(false, _, Some(_)) | (false, ControlFlow::Wait, None) => StartCause::WaitCancelled {
|
||||
requested_resume: None,
|
||||
start: self.last_events_cleared.get(),
|
||||
},
|
||||
(false, ControlFlow::WaitUntil(requested_resume), None) => {
|
||||
if Instant::now() < requested_resume {
|
||||
StartCause::WaitCancelled {
|
||||
requested_resume: Some(requested_resume),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue