Skip to content

Commit

Permalink
on Windows, use a pending redraws set to keep track of request_redraw
Browse files Browse the repository at this point in the history
simplifies the message loops and event handling considerably
strongly inspired from the X11 platform

partially reverts rust-windowing@6a330a2

fixes rust-windowing#1400
fixes rust-windowing#1391
  • Loading branch information
filnet committed Feb 13, 2020
1 parent 5f52d7c commit de54072
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 263 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased

- On Windows, rework handling of request_redraw() to address panics.
- On macOS, fix `set_simple_screen` to remember frame excluding title bar.
- On Wayland, fix coordinates in touch events when scale factor isn't 1.
- On Wayland, fix color from `close_button_icon_color` not applying.
Expand Down
123 changes: 45 additions & 78 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,56 +227,29 @@ impl<T: 'static> EventLoop<T> {
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;
if msg.message == winuser::WM_PAINT {
break;
}
continue;
}

if !unread_message_exists {
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;
}
unread_message_exists = true;
runner.events_cleared();
match runner.control_flow() {
ControlFlow::Exit => break 'main,
ControlFlow::Wait => {
assert!(!unread_message_exists);
if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) {
break 'main;
}
ControlFlow::WaitUntil(resume_time) => {
wait_until_time_or_msg(resume_time);
}
ControlFlow::Poll => (),
unread_message_exists = true;
}
ControlFlow::WaitUntil(resume_time) => {
wait_until_time_or_msg(resume_time);
}
ControlFlow::Poll => (),
}
}
}
Expand Down Expand Up @@ -676,7 +649,6 @@ 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)
}
Expand Down Expand Up @@ -1721,49 +1693,44 @@ 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();
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;
loop {
if 0 == winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 0) {
break;
}

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;
// 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);
}
}

if msg.hwnd != window {
winuser::TranslateMessage(&mut msg);
winuser::DispatchMessageW(&mut msg);
// 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;
}
}
}

// we don't borrow until here because TODO SAFETY
let runner = &subclass_input.event_loop_runner;
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();
}
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();
}
}
}
Expand Down
Loading

0 comments on commit de54072

Please sign in to comment.