mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 13:31:29 +11:00
Fix issues with redraw_requested when called during EventsCleared (#994)
* Fix issues with redraw_requested when called during EventsCleared * Format * Fix event dispatch after RedrawRequested but before EventsCleared This could happen if the event queue was cleared, we processed WM_PAINT, but the event queue got re-filled before we checked to see it was empty. * Fix paint ordering issues when resizing window * Format
This commit is contained in:
parent
9393b14b01
commit
74a7cf55ea
|
@ -9,6 +9,9 @@ and `WindowEvent::HoveredFile`.
|
|||
- Revert the use of invisible surfaces in Wayland, which introduced graphical glitches with OpenGL (#835)
|
||||
- On X11, implement `_NET_WM_PING` to allow desktop environment to kill unresponsive programs.
|
||||
- On Windows, when a window is initially invisible, it won't take focus from the existing visible windows.
|
||||
- On Windows, fix multiple calls to `request_redraw` during `EventsCleared` sending multiple `RedrawRequested events.`
|
||||
- On Windows, fix edge case where `RedrawRequested` could be dispatched before input events in event loop iteration.
|
||||
- On Windows, fix timing issue that could cause events to be improperly dispatched after `RedrawRequested` but before `EventsCleared`.
|
||||
- On macOS, drop unused Metal dependency.
|
||||
|
||||
# 0.20.0 Alpha 1
|
||||
|
|
|
@ -195,6 +195,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
winuser::TranslateMessage(&mut msg);
|
||||
winuser::DispatchMessageW(&mut msg);
|
||||
|
||||
msg_unprocessed = false;
|
||||
}
|
||||
runner!().events_cleared();
|
||||
|
@ -202,19 +203,21 @@ impl<T: 'static> EventLoop<T> {
|
|||
panic::resume_unwind(payload);
|
||||
}
|
||||
|
||||
let control_flow = runner!().control_flow;
|
||||
match control_flow {
|
||||
ControlFlow::Exit => break 'main,
|
||||
ControlFlow::Wait => {
|
||||
if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) {
|
||||
break 'main;
|
||||
if !msg_unprocessed {
|
||||
let control_flow = runner!().control_flow;
|
||||
match control_flow {
|
||||
ControlFlow::Exit => break 'main,
|
||||
ControlFlow::Wait => {
|
||||
if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) {
|
||||
break 'main;
|
||||
}
|
||||
msg_unprocessed = true;
|
||||
}
|
||||
msg_unprocessed = true;
|
||||
ControlFlow::WaitUntil(resume_time) => {
|
||||
wait_until_time_or_msg(resume_time);
|
||||
}
|
||||
ControlFlow::Poll => (),
|
||||
}
|
||||
ControlFlow::WaitUntil(resume_time) => {
|
||||
wait_until_time_or_msg(resume_time);
|
||||
}
|
||||
ControlFlow::Poll => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -253,6 +256,7 @@ pub(crate) struct EventLoopRunner<T> {
|
|||
runner_state: RunnerState,
|
||||
modal_redraw_window: HWND,
|
||||
in_modal_loop: bool,
|
||||
in_repaint: bool,
|
||||
event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>,
|
||||
panic_error: Option<PanicError>,
|
||||
}
|
||||
|
@ -316,6 +320,7 @@ impl<T> EventLoopRunner<T> {
|
|||
control_flow: ControlFlow::default(),
|
||||
runner_state: RunnerState::New,
|
||||
in_modal_loop: false,
|
||||
in_repaint: false,
|
||||
modal_redraw_window: event_loop.window_target.p.thread_msg_target,
|
||||
event_handler: mem::transmute::<
|
||||
Box<dyn FnMut(Event<T>, &mut ControlFlow)>,
|
||||
|
@ -429,10 +434,26 @@ impl<T> EventLoopRunner<T> {
|
|||
}
|
||||
|
||||
self.runner_state = RunnerState::HandlingEvents;
|
||||
self.call_event_handler(event);
|
||||
match (self.in_repaint, &event) {
|
||||
(
|
||||
true,
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::RedrawRequested,
|
||||
..
|
||||
},
|
||||
)
|
||||
| (false, _) => self.call_event_handler(event),
|
||||
(true, _) => {
|
||||
self.events_cleared();
|
||||
self.new_events();
|
||||
self.process_event(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn events_cleared(&mut self) {
|
||||
self.in_repaint = false;
|
||||
|
||||
match self.runner_state {
|
||||
// If we were handling events, send the EventsCleared message.
|
||||
RunnerState::HandlingEvents => {
|
||||
|
@ -483,6 +504,10 @@ impl<T> EventLoopRunner<T> {
|
|||
Event::EventsCleared => self
|
||||
.trigger_newevents_on_redraw
|
||||
.store(false, Ordering::Relaxed),
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::RedrawRequested,
|
||||
..
|
||||
} => self.in_repaint = true,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
|
@ -871,12 +896,12 @@ unsafe extern "system" fn public_window_callback<T>(
|
|||
_ if msg == *REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID => {
|
||||
use crate::event::WindowEvent::RedrawRequested;
|
||||
let mut runner = subclass_input.event_loop_runner.runner.borrow_mut();
|
||||
subclass_input.window_state.lock().queued_out_of_band_redraw = false;
|
||||
if let Some(ref mut runner) = *runner {
|
||||
// This check makes sure that calls to `request_redraw()` during `EventsCleared`
|
||||
// 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.
|
||||
let control_flow = runner.control_flow;
|
||||
let runner_state = runner.runner_state;
|
||||
let mut request_redraw = || {
|
||||
runner.call_event_handler(Event::WindowEvent {
|
||||
|
@ -886,15 +911,14 @@ unsafe extern "system" fn public_window_callback<T>(
|
|||
};
|
||||
match 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()
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
RunnerState::HandlingEvents => {
|
||||
winuser::RedrawWindow(
|
||||
window,
|
||||
ptr::null(),
|
||||
ptr::null_mut(),
|
||||
winuser::RDW_INTERNALPAINT,
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,11 @@ impl Window {
|
|||
winuser::RDW_INTERNALPAINT,
|
||||
);
|
||||
} else {
|
||||
winuser::PostMessageW(self.window.0, *REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID, 0, 0);
|
||||
let mut window_state = self.window_state.lock();
|
||||
if !window_state.queued_out_of_band_redraw {
|
||||
window_state.queued_out_of_band_redraw = true;
|
||||
winuser::PostMessageW(self.window.0, *REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ pub struct WindowState {
|
|||
pub dpi_factor: f64,
|
||||
|
||||
pub fullscreen: Option<MonitorHandle>,
|
||||
/// Used to supress duplicate redraw attempts when calling `request_redraw` multiple
|
||||
/// times in `EventsCleared`.
|
||||
pub queued_out_of_band_redraw: bool,
|
||||
window_flags: WindowFlags,
|
||||
}
|
||||
|
||||
|
@ -110,6 +113,7 @@ impl WindowState {
|
|||
dpi_factor,
|
||||
|
||||
fullscreen: None,
|
||||
queued_out_of_band_redraw: false,
|
||||
window_flags: WindowFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue