On Windows, fix bug where RedrawRequested would only get emitted every other iteration of the event loop (#1366)
* Fix bug causing RedrawRequested events to only get emitted every other iteration of the event loop. * Initialize simple_logger in examples. This PR's primary bug was discovered because a friend of mine reported that winit was emitting concerning log messages, which I'd never seen since none of the examples print out the log messages. This addresses that, to hopefully reduce the chance of bugs going unnoticed in the future. * Add changelog entry * Format
This commit is contained in:
parent
627a127f1b
commit
6a330a2894
25 changed files with 329 additions and 128 deletions
|
|
@ -100,13 +100,9 @@ pub(crate) struct SubclassInput<T: 'static> {
|
|||
}
|
||||
|
||||
impl<T> SubclassInput<T> {
|
||||
unsafe fn send_event(&self, event: Event<'static, T>) {
|
||||
unsafe fn send_event(&self, event: Event<'_, T>) {
|
||||
self.event_loop_runner.send_event(event);
|
||||
}
|
||||
|
||||
unsafe fn send_event_unbuffered<'e>(&self, event: Event<'e, T>) -> Result<(), Event<'e, T>> {
|
||||
self.event_loop_runner.send_event_unbuffered(event)
|
||||
}
|
||||
}
|
||||
|
||||
struct ThreadMsgTargetSubclassInput<T: 'static> {
|
||||
|
|
@ -116,7 +112,7 @@ struct ThreadMsgTargetSubclassInput<T: 'static> {
|
|||
}
|
||||
|
||||
impl<T> ThreadMsgTargetSubclassInput<T> {
|
||||
unsafe fn send_event(&self, event: Event<'static, T>) {
|
||||
unsafe fn send_event(&self, event: Event<'_, T>) {
|
||||
self.event_loop_runner.send_event(event);
|
||||
}
|
||||
}
|
||||
|
|
@ -216,28 +212,57 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
unsafe {
|
||||
let mut msg = mem::zeroed();
|
||||
let mut msg_unprocessed = false;
|
||||
let mut unread_message_exists = false;
|
||||
|
||||
'main: loop {
|
||||
runner.new_events();
|
||||
loop {
|
||||
if !msg_unprocessed {
|
||||
if 0 == winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
winuser::TranslateMessage(&mut msg);
|
||||
winuser::DispatchMessageW(&mut msg);
|
||||
|
||||
msg_unprocessed = false;
|
||||
}
|
||||
runner.events_cleared();
|
||||
if let Err(payload) = runner.take_panic_error() {
|
||||
runner.destroy_runner();
|
||||
panic::resume_unwind(payload);
|
||||
}
|
||||
|
||||
if !msg_unprocessed {
|
||||
runner.new_events();
|
||||
loop {
|
||||
if !unread_message_exists {
|
||||
if 0 == winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if msg.message == winuser::WM_PAINT {
|
||||
unread_message_exists = true;
|
||||
break;
|
||||
}
|
||||
winuser::TranslateMessage(&mut msg);
|
||||
winuser::DispatchMessageW(&mut msg);
|
||||
|
||||
unread_message_exists = false;
|
||||
}
|
||||
runner.main_events_cleared();
|
||||
loop {
|
||||
if !unread_message_exists {
|
||||
if 0 == winuser::PeekMessageW(
|
||||
&mut msg,
|
||||
ptr::null_mut(),
|
||||
winuser::WM_PAINT,
|
||||
winuser::WM_PAINT,
|
||||
1,
|
||||
) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
winuser::TranslateMessage(&mut msg);
|
||||
winuser::DispatchMessageW(&mut msg);
|
||||
|
||||
unread_message_exists = false;
|
||||
}
|
||||
if runner.redraw_events_cleared().events_buffered() {
|
||||
if runner.control_flow() == ControlFlow::Exit {
|
||||
break 'main;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if !unread_message_exists {
|
||||
let control_flow = runner.control_flow();
|
||||
match control_flow {
|
||||
ControlFlow::Exit => break 'main,
|
||||
|
|
@ -245,7 +270,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) {
|
||||
break 'main;
|
||||
}
|
||||
msg_unprocessed = true;
|
||||
unread_message_exists = true;
|
||||
}
|
||||
ControlFlow::WaitUntil(resume_time) => {
|
||||
wait_until_time_or_msg(resume_time);
|
||||
|
|
@ -651,6 +676,7 @@ unsafe extern "system" fn public_window_callback<T: 'static>(
|
|||
}
|
||||
|
||||
winuser::WM_PAINT => {
|
||||
subclass_input.event_loop_runner.main_events_cleared();
|
||||
subclass_input.send_event(Event::RedrawRequested(RootWindowId(WindowId(window))));
|
||||
commctrl::DefSubclassProc(window, msg, wparam, lparam)
|
||||
}
|
||||
|
|
@ -1497,7 +1523,7 @@ unsafe extern "system" fn public_window_callback<T: 'static>(
|
|||
false => old_physical_inner_size,
|
||||
};
|
||||
|
||||
let _ = subclass_input.send_event_unbuffered(Event::WindowEvent {
|
||||
let _ = subclass_input.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(WindowId(window)),
|
||||
event: ScaleFactorChanged {
|
||||
scale_factor: new_dpi_factor,
|
||||
|
|
@ -1697,44 +1723,49 @@ unsafe extern "system" fn thread_event_target_callback<T: 'static>(
|
|||
let in_modal_loop = subclass_input.event_loop_runner.in_modal_loop();
|
||||
if in_modal_loop {
|
||||
let mut msg = mem::zeroed();
|
||||
loop {
|
||||
if 0 == winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 0) {
|
||||
break;
|
||||
if 0 == winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 0) {
|
||||
if msg.message != 0 && msg.message != winuser::WM_PAINT {
|
||||
queue_call_again();
|
||||
return 0;
|
||||
}
|
||||
// Clear all paint/timer messages from the queue before sending the events cleared message.
|
||||
match msg.message {
|
||||
// Flush the event queue of WM_PAINT messages.
|
||||
winuser::WM_PAINT | winuser::WM_TIMER => {
|
||||
// Remove the message from the message queue.
|
||||
winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 1);
|
||||
|
||||
if msg.hwnd != window {
|
||||
winuser::TranslateMessage(&mut msg);
|
||||
winuser::DispatchMessageW(&mut msg);
|
||||
}
|
||||
subclass_input.event_loop_runner.main_events_cleared();
|
||||
loop {
|
||||
if 0 == winuser::PeekMessageW(
|
||||
&mut msg,
|
||||
ptr::null_mut(),
|
||||
winuser::WM_PAINT,
|
||||
winuser::WM_PAINT,
|
||||
1,
|
||||
) {
|
||||
break;
|
||||
}
|
||||
// If the message isn't one of those three, it may be handled by the modal
|
||||
// loop so we should return control flow to it.
|
||||
_ => {
|
||||
queue_call_again();
|
||||
return 0;
|
||||
|
||||
if msg.hwnd != window {
|
||||
winuser::TranslateMessage(&mut msg);
|
||||
winuser::DispatchMessageW(&mut msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we don't borrow until here because TODO SAFETY
|
||||
let runner = &subclass_input.event_loop_runner;
|
||||
runner.events_cleared();
|
||||
match runner.control_flow() {
|
||||
// Waiting is handled by the modal loop.
|
||||
ControlFlow::Exit | ControlFlow::Wait => runner.new_events(),
|
||||
ControlFlow::WaitUntil(resume_time) => {
|
||||
wait_until_time_or_msg(resume_time);
|
||||
runner.new_events();
|
||||
queue_call_again();
|
||||
}
|
||||
ControlFlow::Poll => {
|
||||
runner.new_events();
|
||||
queue_call_again();
|
||||
if runner.redraw_events_cleared().events_buffered() {
|
||||
queue_call_again();
|
||||
runner.new_events();
|
||||
} else {
|
||||
match runner.control_flow() {
|
||||
// Waiting is handled by the modal loop.
|
||||
ControlFlow::Exit | ControlFlow::Wait => runner.new_events(),
|
||||
ControlFlow::WaitUntil(resume_time) => {
|
||||
wait_until_time_or_msg(resume_time);
|
||||
runner.new_events();
|
||||
queue_call_again();
|
||||
}
|
||||
ControlFlow::Poll => {
|
||||
runner.new_events();
|
||||
queue_call_again();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue