Fix control flow issues with Window::request_redraw (eventloop-2.0) (#890)

* Fix request_redraw with Poll and WaitUntil(time_in_the_past) on Windows

`Window::request_redraw` now fires a `RedrawRequested` event when
called from an `Event::EventsCleared` callback while the control
flow is set to `Poll`. A control flow of `WaitUntil(resume_time)`,
will now also fire the `RedrawRequested` event when `resume_time`
is in the past.

* Prevent panic on x11 when WaitUntil(resume_time) is in the past

* Prevent panic on wayland when WaitUntil(resume_time) is in the past
This commit is contained in:
aloucks 2019-05-30 00:33:52 -04:00 committed by Hal Gentz
parent 0df436901a
commit 08f8f89702
3 changed files with 29 additions and 6 deletions

View file

@ -266,7 +266,11 @@ impl<T: 'static> EventLoop<T> {
ControlFlow::WaitUntil(deadline) => {
let start = Instant::now();
// compute the blocking duration
let duration = deadline.duration_since(::std::cmp::max(deadline, start));
let duration = if deadline > start {
deadline - start
} else {
::std::time::Duration::from_millis(0)
};
self.inner_loop.dispatch(Some(duration), &mut ()).unwrap();
control_flow = ControlFlow::default();
let now = Instant::now();

View file

@ -301,7 +301,11 @@ impl<T: 'static> EventLoop<T> {
ControlFlow::WaitUntil(deadline) => {
let start = ::std::time::Instant::now();
// compute the blocking duration
let duration = deadline.duration_since(::std::cmp::max(deadline, start));
let duration = if deadline > start {
deadline - start
} else {
::std::time::Duration::from_millis(0)
};
self.inner_loop.dispatch(Some(duration), &mut ()).unwrap();
control_flow = ControlFlow::default();
let now = std::time::Instant::now();

View file

@ -843,12 +843,27 @@ unsafe extern "system" fn public_window_callback<T>(
// handling dispatch `RedrawRequested` immediately after `EventsCleared`, without
// spinning up a new event loop iteration. We do this because that's what the API
// says to do.
match runner.runner_state {
RunnerState::Idle(..) |
RunnerState::DeferredNewEvents(..) => runner.call_event_handler(Event::WindowEvent {
let control_flow = runner.control_flow;
let mut request_redraw = || {
runner.call_event_handler(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)),
event: RedrawRequested,
}),
});
};
match runner.runner_state {
RunnerState::Idle(..) |
RunnerState::DeferredNewEvents(..) => request_redraw(),
RunnerState::HandlingEvents => {
match control_flow {
ControlFlow::Poll => request_redraw(),
ControlFlow::WaitUntil(resume_time) => {
if resume_time <= Instant::now() {
request_redraw()
}
},
_ => ()
}
}
_ => ()
}
}