Skip to content

win32: fix multi-window redraw starvation - #4653

Open
Niketion wants to merge 5 commits into
rust-windowing:masterfrom
Niketion:fix/win32-multi-window-redraw-3648
Open

win32: fix multi-window redraw starvation#4653
Niketion wants to merge 5 commits into
rust-windowing:masterfrom
Niketion:fix/win32-multi-window-redraw-3648

Conversation

@Niketion

@Niketion Niketion commented Jul 31, 2026

Copy link
Copy Markdown
  • Tested on all platforms changed (Windows)
  • Added an entry to the changelog module if knowledge of this change could be valuable to users
  • Updated the internal dispatch documentation
  • Created or updated an example program if it would help users understand this functionality

Fixes #3648.

Multi-window redraw starvation

Dispatching a RedrawRequested interrupts Win32 message processing so that pump_app_events can promptly return control to its external event loop.

Previously, the next iteration could enter the wait phase and emit another AboutToWait before dispatching the remaining queued window messages. Applications requesting redraws again from AboutToWait could therefore repeatedly service one window while starving the others.

This change preserves the interrupted-dispatch state across pump_app_events calls and resumes pending message dispatch before entering another wait phase. run_app_on_demand likewise checks the interrupted state before preparing to wait. This restores fairness between windows while preserving pump_app_events behavior of returning after one RedrawRequested.

Testing

Tested on Windows across:

  • ControlFlow::Wait and ControlFlow::Poll;
  • run_app, run_app_on_demand, and pump_app_events;
  • multiple windows and different redraw request orders;
  • redraw requests made from inside RedrawRequested;
  • cross-thread requests, window state changes, closure, and exit handling.

With equal request counts, the original five-window reproducer produced:

events=[0, 0, 0, 0, 500]

With this change:

events=[500, 500, 500, 500, 500]

Resume a redraw-interrupted message dispatch before entering the next wait phase. This prevents another `AboutToWait` from issuing redraw requests before other pending window paints are dispatched, while preserving `pump_app_events`' one-redraw return behavior.
Deliver explicit redraw requests through a posted window message instead of low-priority WM_PAINT. This prevents a continuously populated message queue from starving RedrawRequested while preserving coalescing, system paints, re-entrant callbacks, and source-drag behavior.
@Niketion
Niketion force-pushed the fix/win32-multi-window-redraw-3648 branch from f7373b9 to 846ea56 Compare August 5, 2026 12:00
@Niketion Niketion changed the title win32: fix multi-window redraw starvation win32: fix redraw starvation across windows and continuous input Aug 5, 2026
@nicoburns

Copy link
Copy Markdown
Contributor

I believe this PR currently has a problem where it will schedule a redraw for every single input event if the handler every event requests redraw, with no coalescing at all. I think we need some kind of middle ground where input events are processed in a batch up until some deadline or similar.

@Niketion

Niketion commented Aug 5, 2026

Copy link
Copy Markdown
Author

Thanks, this is a valid concern. Addressing this correctly would require a more deliberate batching or deadline policy, together with broader testing across run_app, pump_app_events, multiple windows, and native modal loops. I think that goes beyond the original scope of this PR.

I’m going to revert the continuous-input/posted-message changes for now and keep this PR focused on the original multi-window starvation issue in #3648

@Niketion Niketion changed the title win32: fix redraw starvation across windows and continuous input win32: fix multi-window redraw starvation Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Not receiving RedrawRequested events for all windows that .request_redraw()

2 participants