Skip to content

Commit

Permalink
Remove most RedrawWindow to event target window (#427)
Browse files Browse the repository at this point in the history
* Remove most RedrawWindow to event tartget window

* Add workaround to handle clear event

* Add change file
  • Loading branch information
Ngo Iok Ui (Wu Yu Wei) committed Jun 28, 2022
1 parent 6782f65 commit 5ca39af
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changes/wmpaint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
tao: "patch"
---

Reduce `WM_PAINT` singal on event target window to prevent from webview2 delay.
44 changes: 24 additions & 20 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2051,8 +2051,10 @@ unsafe extern "system" fn thread_event_target_callback<T: 'static>(
) -> LRESULT {
let subclass_input = Box::from_raw(subclass_input_ptr as *mut ThreadMsgTargetSubclassInput<T>);

// 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 {
RedrawWindow(window, ptr::null(), HRGN::default(), RDW_INTERNALPAINT);
handle_clear_event(&subclass_input.event_loop_runner, window);
}

let mut subclass_removed = false;
Expand All @@ -2070,25 +2072,8 @@ unsafe extern "system" fn thread_event_target_callback<T: 'static>(
// 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)
Expand Down Expand Up @@ -2356,3 +2341,22 @@ unsafe fn handle_raw_input<T: 'static>(
});
}
}

unsafe fn handle_clear_event<T: 'static>(event_loop_runner: &EventLoopRunner<T>, 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);
}
}
}
23 changes: 17 additions & 6 deletions src/platform_impl/windows/event_loop/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,13 @@ impl<T> EventLoopRunner<T> {
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.
Expand Down Expand Up @@ -394,12 +401,16 @@ impl<T> EventLoopRunner<T> {
};
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) {
Expand Down

0 comments on commit 5ca39af

Please sign in to comment.