Skip to content

Commit 5ca39af

Browse files
author
Ngo Iok Ui (Wu Yu Wei)
authored
Remove most RedrawWindow to event target window (#427)
* Remove most RedrawWindow to event tartget window * Add workaround to handle clear event * Add change file
1 parent 6782f65 commit 5ca39af

3 files changed

Lines changed: 46 additions & 26 deletions

File tree

.changes/wmpaint.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
tao: "patch"
3+
---
4+
5+
Reduce `WM_PAINT` singal on event target window to prevent from webview2 delay.

src/platform_impl/windows/event_loop.rs

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2051,8 +2051,10 @@ unsafe extern "system" fn thread_event_target_callback<T: 'static>(
20512051
) -> LRESULT {
20522052
let subclass_input = Box::from_raw(subclass_input_ptr as *mut ThreadMsgTargetSubclassInput<T>);
20532053

2054+
// Calling RedrawWindow will cause other window busy waiting. So we handle clear event directly
2055+
// as long as there's a thread event target message.
20542056
if msg != WM_PAINT {
2055-
RedrawWindow(window, ptr::null(), HRGN::default(), RDW_INTERNALPAINT);
2057+
handle_clear_event(&subclass_input.event_loop_runner, window);
20562058
}
20572059

20582060
let mut subclass_removed = false;
@@ -2070,25 +2072,8 @@ unsafe extern "system" fn thread_event_target_callback<T: 'static>(
20702072
// when the event queue has been emptied. See `process_event` for more details.
20712073
win32wm::WM_PAINT => {
20722074
ValidateRect(window, ptr::null());
2073-
// If the WM_PAINT handler in `public_window_callback` has already flushed the redraw
2074-
// events, `handling_events` will return false and we won't emit a second
2075-
// `RedrawEventsCleared` event.
2076-
if subclass_input.event_loop_runner.handling_events() {
2077-
if subclass_input.event_loop_runner.should_buffer() {
2078-
// This branch can be triggered when a nested win32 event loop is triggered
2079-
// inside of the `event_handler` callback.
2080-
RedrawWindow(window, ptr::null(), HRGN::default(), RDW_INTERNALPAINT);
2081-
} else {
2082-
// This WM_PAINT handler will never be re-entrant because `flush_paint_messages`
2083-
// doesn't call WM_PAINT for the thread event target (i.e. this window).
2084-
assert!(flush_paint_messages(
2085-
None,
2086-
&subclass_input.event_loop_runner
2087-
));
2088-
subclass_input.event_loop_runner.redraw_events_cleared();
2089-
process_control_flow(&subclass_input.event_loop_runner);
2090-
}
2091-
}
2075+
2076+
handle_clear_event(&subclass_input.event_loop_runner, window);
20922077

20932078
// Default WM_PAINT behaviour. This makes sure modals and popups are shown immediatly when opening them.
20942079
DefSubclassProc(window, msg, wparam, lparam)
@@ -2356,3 +2341,22 @@ unsafe fn handle_raw_input<T: 'static>(
23562341
});
23572342
}
23582343
}
2344+
2345+
unsafe fn handle_clear_event<T: 'static>(event_loop_runner: &EventLoopRunner<T>, window: HWND) {
2346+
// If the WM_PAINT handler in `public_window_callback` has already flushed the redraw
2347+
// events, `handling_events` will return false and we won't emit a second
2348+
// `RedrawEventsCleared` event.
2349+
if event_loop_runner.handling_events() {
2350+
if event_loop_runner.should_buffer() {
2351+
// This branch can be triggered when a nested win32 event loop is triggered
2352+
// inside of the `event_handler` callback.
2353+
RedrawWindow(window, ptr::null(), HRGN::default(), RDW_INTERNALPAINT);
2354+
} else {
2355+
// This WM_PAINT handler will never be re-entrant because `flush_paint_messages`
2356+
// doesn't call WM_PAINT for the thread event target (i.e. this window).
2357+
assert!(flush_paint_messages(None, &event_loop_runner));
2358+
event_loop_runner.redraw_events_cleared();
2359+
process_control_flow(&event_loop_runner);
2360+
}
2361+
}
2362+
}

src/platform_impl/windows/event_loop/runner.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@ impl<T> EventLoopRunner<T> {
196196
owned_windows.extend(&new_owned_windows);
197197
self.owned_windows.set(owned_windows);
198198
}
199+
200+
pub fn no_owned_windows(&self) -> bool {
201+
let owned_windows = self.owned_windows.take();
202+
let result = owned_windows.is_empty();
203+
self.owned_windows.set(owned_windows);
204+
result
205+
}
199206
}
200207

201208
/// Event dispatch functions.
@@ -394,12 +401,16 @@ impl<T> EventLoopRunner<T> {
394401
};
395402
self.call_event_handler(Event::NewEvents(start_cause));
396403
self.dispatch_buffered_events();
397-
RedrawWindow(
398-
self.thread_msg_target,
399-
ptr::null(),
400-
HRGN::default(),
401-
RDW_INTERNALPAINT,
402-
);
404+
// Calling RedrawWindow will cause other window busy waiting. So we only call it when
405+
// there's no window.
406+
if self.no_owned_windows() {
407+
RedrawWindow(
408+
self.thread_msg_target,
409+
ptr::null(),
410+
HRGN::default(),
411+
RDW_INTERNALPAINT,
412+
);
413+
}
403414
}
404415

405416
unsafe fn call_redraw_events_cleared(&self) {

0 commit comments

Comments
 (0)