Skip to content

Fix missed RedrawRequested and WindowCloseRequested events with UpdateMode::Reactive (part 2) #18549

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

aloucks
Copy link
Contributor

@aloucks aloucks commented Mar 25, 2025

Objective

This PR continues the work started by @boondocklabs in #17991 in order to fix missed RedrawRequested events that are sent during app update. Additionally, this PR now also fixes a similar issue where WindowCloseRequested events were also missed during app update. In both cases, the event would not be handled until the next app update.

This bug applies when the app is running with UpdateMode::Reactive. These missed events won't be handled until the next event loop timeout or triggered by a new window or device event (such as moving the mouse).

Use-Cases

When using UpdateMode::Reactive:

  1. Sending a RedrawRequested event from an observe system should trigger a redraw immediately. The app should not stall until the next window event or event loop timeout.
  2. Clicking the close button on a window should be handled immediately. The app should not stall until the next window event or event loop timeout.

Solution

  • RedrawRequested events are already read and checked in the winit event loop runner. Move this read after the app update executes.
  • WindowCloseRequested were not previously read or checked. Read and check if an event has fired after the app update executes.

Prior Art

The UpdateMode itself is (re)read after the app update with a note about re-extracting it since the app update may have changed the value and we should act accordingly. We're essentially applying this same logic (i.e. check after the app update) for RedrawRequested and WindowCloseRequested.

Original PR Notes from @boondocklabs

Solution

Currently RequestRedraw events can be missed in about_to_wait() as it is can call run_app_update() after reading the event cursor, thus the redraw_requested flag is stale.

This adds a subsequent read after the call to run_app_update to ensure redraw_requested is updated if any events were sent during the update.

Testing

Tested in Reactive mode with animations using a forked bevy_tweening which supports 0.16-dev and sends RequestRedraw events while there are any Animator components active.

Prior to this change, the animation would only run a single update, and would stall for the reactive mode timeout before continuing the animation.

With this patch, the animation runs smooth in Reactive mode. Tested on MacOS and iOS on iPad and iPhone.

@aloucks aloucks force-pushed the fix-missed-request-redraw branch from 4e09f2b to 9218c8a Compare March 25, 2025 20:52
@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-Windowing Platform-agnostic interface layer to run your app in S-Needs-Review Needs reviewer attention (from anyone!) to move forward D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes labels Mar 25, 2025
@aloucks aloucks force-pushed the fix-missed-request-redraw branch from 9218c8a to 0bcd3a9 Compare March 25, 2025 21:20
@aloucks
Copy link
Contributor Author

aloucks commented Mar 26, 2025

The test included in this PR uses observe which I suspect is resulting in the event delivery being deferred. The low_power example works as expected with or without this change but does not use an Observer.

@aloucks
Copy link
Contributor Author

aloucks commented Mar 29, 2025

Prior to this change, the animation would only run a single update, and would stall for the reactive mode timeout before continuing the animation.

There's another similar issue where WindowCloseRequested is also not handled immediately in reactive mode. If you run the low_power example, press space to enter reactive mode, and then attempt to close the window, nothing happens for a second or two. The timing of these varies from run to run, but if you do it repeatedly, you'll definitely notice a short delay between pressing the the window close button and when the window actually closes.

The fix for the window delay issue is essentially the same as what's presented here - read the WindowCloseRequested events after the app update and toggle request_redraw if one came through.

@aloucks
Copy link
Contributor Author

aloucks commented Mar 29, 2025

@alice-i-cecile

Is there any way we could get this in for 0.16? I understand you want to lock down new features, but this feels like a pretty decent UX bugfix. I've tested these changes on macOS and Windows. Please let me know if there is anything I can do to help make this happen for 0.16.

Thanks!

@alice-i-cecile
Copy link
Member

I need testing and reviews from at least two other contributors, ideally on a wide range of platforms. I share your desire to get this sort of bug fix in, but windowing code is really fragile and hard to test.

boondocklabs and others added 7 commits March 30, 2025 01:25
This fixes RequestRedraw events that can be missed in `about_to_wait()` which was reading from the cursor before `run_app_update()` is called.

This adds a subsequent read to update the redraw_requested flag if any `RequestRedraw` were sent.

Was reported in bevyengine#16817
They are now read after the world update.
Pressing the window close button when in a reactive UpdateMode
isn't handled until the reactive wait timeout is triggered or
the user triggers some other device event. This change adds an
explict check for the WindowCloseRequested event to trigger
another app update to process it.
@aloucks aloucks force-pushed the fix-missed-request-redraw branch from 4f19374 to 4c116a9 Compare March 30, 2025 05:26
@aloucks aloucks changed the title Fix missed request redraw (part 2) Fix missed RedrawRequested and WindowCloseRequested events (part 2) Mar 30, 2025
@aloucks aloucks changed the title Fix missed RedrawRequested and WindowCloseRequested events (part 2) Fix missed RedrawRequested and WindowCloseRequested events with UpdateMode::Reactive (part 2) Mar 30, 2025
@tychedelia
Copy link
Contributor

Can you provide some brief info about how to test this? Just the low_power example?

@aloucks
Copy link
Contributor Author

aloucks commented Mar 31, 2025

Can you provide some brief info about how to test this? Just the low_power example?

There's two things to test with UpdateMode::Reactive:

  1. Handling of RedrawRequested:
  2. Handling of WindowCloseRequested :
    • On the main branch: If you run the low_power example, press space to enter reactive mode, and then attempt to close the window, nothing happens for a second or two. The timing of these varies from run to run, but if you do it repeatedly, you'll definitely notice a short delay between pressing the the window close button and when the window actually closes.
    • If you run these steps with this branch, the window will close immediately.

@aloucks
Copy link
Contributor Author

aloucks commented May 3, 2025

Is there any other info needed for testing?

@tychedelia tychedelia added this to the 0.17 milestone May 7, 2025
@tychedelia
Copy link
Contributor

Hi! Thanks for checking back in. I haven't had time to look into this but it's in my inbox. I've also added it to 0.17 to make sure it doesn't get missed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Windowing Platform-agnostic interface layer to run your app in C-Bug An unexpected or incorrect behavior D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants