diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 741eccc56..4f11e01dd 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -2018,9 +2018,11 @@ unsafe extern "system" fn thread_event_target_callback( ) -> LRESULT { let subclass_input = Box::from_raw(subclass_input_ptr as *mut ThreadMsgTargetSubclassInput); - // if msg != WM_PAINT { - // RedrawWindow(window, ptr::null(), HRGN::default(), RDW_INTERNALPAINT); - // } + // Calling RedrawWindow will cause other window busy waiting. So we handle clear event directly + // as long as there's a thread event target message. + if msg != WM_PAINT { + handle_clear_event(&subclass_input.event_loop_runner, window); + } let mut subclass_removed = false; @@ -2037,25 +2039,8 @@ unsafe extern "system" fn thread_event_target_callback( // when the event queue has been emptied. See `process_event` for more details. win32wm::WM_PAINT => { ValidateRect(window, ptr::null()); - // If the WM_PAINT handler in `public_window_callback` has already flushed the redraw - // events, `handling_events` will return false and we won't emit a second - // `RedrawEventsCleared` event. - if subclass_input.event_loop_runner.handling_events() { - if subclass_input.event_loop_runner.should_buffer() { - // This branch can be triggered when a nested win32 event loop is triggered - // inside of the `event_handler` callback. - RedrawWindow(window, ptr::null(), HRGN::default(), RDW_INTERNALPAINT); - } else { - // This WM_PAINT handler will never be re-entrant because `flush_paint_messages` - // doesn't call WM_PAINT for the thread event target (i.e. this window). - assert!(flush_paint_messages( - None, - &subclass_input.event_loop_runner - )); - subclass_input.event_loop_runner.redraw_events_cleared(); - process_control_flow(&subclass_input.event_loop_runner); - } - } + + handle_clear_event(&subclass_input.event_loop_runner, window); // Default WM_PAINT behaviour. This makes sure modals and popups are shown immediatly when opening them. DefSubclassProc(window, msg, wparam, lparam) @@ -2323,3 +2308,22 @@ unsafe fn handle_raw_input( }); } } + +unsafe fn handle_clear_event(event_loop_runner: &EventLoopRunner, window: HWND) { + // If the WM_PAINT handler in `public_window_callback` has already flushed the redraw + // events, `handling_events` will return false and we won't emit a second + // `RedrawEventsCleared` event. + if event_loop_runner.handling_events() { + if event_loop_runner.should_buffer() { + // This branch can be triggered when a nested win32 event loop is triggered + // inside of the `event_handler` callback. + RedrawWindow(window, ptr::null(), HRGN::default(), RDW_INTERNALPAINT); + } else { + // This WM_PAINT handler will never be re-entrant because `flush_paint_messages` + // doesn't call WM_PAINT for the thread event target (i.e. this window). + assert!(flush_paint_messages(None, &event_loop_runner)); + event_loop_runner.redraw_events_cleared(); + process_control_flow(&event_loop_runner); + } + } +} diff --git a/src/platform_impl/windows/event_loop/runner.rs b/src/platform_impl/windows/event_loop/runner.rs index 7f269b35c..cce59f3b1 100644 --- a/src/platform_impl/windows/event_loop/runner.rs +++ b/src/platform_impl/windows/event_loop/runner.rs @@ -196,6 +196,13 @@ impl EventLoopRunner { owned_windows.extend(&new_owned_windows); self.owned_windows.set(owned_windows); } + + pub fn no_owned_windows(&self) -> bool { + let owned_windows = self.owned_windows.take(); + let result = owned_windows.is_empty(); + self.owned_windows.set(owned_windows); + result + } } /// Event dispatch functions. @@ -394,12 +401,16 @@ impl EventLoopRunner { }; self.call_event_handler(Event::NewEvents(start_cause)); self.dispatch_buffered_events(); - // RedrawWindow( - // self.thread_msg_target, - // ptr::null(), - // HRGN::default(), - // RDW_INTERNALPAINT, - // ); + // Calling RedrawWindow will cause other window busy waiting. So we only call it when + // there's no window. + if self.no_owned_windows() { + RedrawWindow( + self.thread_msg_target, + ptr::null(), + HRGN::default(), + RDW_INTERNALPAINT, + ); + } } unsafe fn call_redraw_events_cleared(&self) {