Skip to content
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

Fix a pause in the event loop when clicking the title bar on windows #4136

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

aloucks
Copy link
Contributor

@aloucks aloucks commented Feb 23, 2025

When clicking the title bar on Windows, to drag the window, there is a noticeable ~500ms pause in continuous redraw requests. This was fixed in #839 and then regressed in #1852. The cursor blinks in both cases and is unrelated. The regression made the blink happen after the pause instead of immediately.

  • Tested on all platforms changed
  • Added an entry to the changelog module if knowledge of this change could be valuable to users

@aloucks aloucks requested a review from notgull as a code owner February 23, 2025 20:25
@madsmtm madsmtm added B - bug Dang, that shouldn't have happened DS - windows labels Feb 24, 2025
@madsmtm
Copy link
Member

madsmtm commented Mar 1, 2025

Will this fix #1885 too?

@aloucks
Copy link
Contributor Author

aloucks commented Mar 1, 2025

Will this fix #1885 too?

Yes

@madsmtm madsmtm added this to the Version 0.31.0 milestone Mar 1, 2025
When clicking the title bar on Windows, to drag the window, there is
a noticible pause in continuous redraw requests. This was fixed
in rust-windowing#839 and then regressed in rust-windowing#1852. The cursor blinks in both
cases and is unrelated. The regression made the blink happen after
the pause instead of immediately.
Copy link
Member

@madsmtm madsmtm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I would quite like to get this fix in, as I believe it's desired by Bevy people, but we don't really have a Windows maintainer at the moment, and I don't feel like I understand enough of what's going on here myself to confidently merge this.

Maybe you could expand on why the PostMessageW is necessary in the first place (why is the default handler not sufficient?), why passing lparam = 0 is correct, and if you know, how we'd go about fixing the blinking then? Ideally as code-comments with links to official docs, makes it easier to track in the future.

Also CC author of #1852 @Ssaely

@aloucks
Copy link
Contributor Author

aloucks commented Mar 9, 2025

So, I would quite like to get this fix in, as I believe it's desired by Bevy people, but we don't really have a Windows maintainer at the moment, and I don't feel like I understand enough of what's going on here myself to confidently merge this.

Maybe you could expand on why the PostMessageW is necessary in the first place (why is the default handler not sufficient?), why passing lparam = 0 is correct, and if you know, how we'd go about fixing the blinking then? Ideally as code-comments with links to official docs, makes it easier to track in the future.

Also CC author of #1852 @Ssaely

To be honest, I fixed this 6 years ago and I don't really remember the details. I noticed it had regressed while exploring something else. The blinking happens even when the entire WM_NCLBUTTONDOWN event handler is commented out. The primary difference is that with the change, it blinks immediately instead of after the short pause.

The short pause is ingrained in how Windows works. If you start dragging the window immediately when you click, you won't notice a pause.

I think what's happening is that the dummy WM_MOUSEMOVE is received in the system modal event loop and simulates a window drag, which cancels the pause. This would explain why the application never sees the dummy event.

I'm completely speculating here, but I'm guessing that windows is computing a delta to determine drag status and (0, 0) is always going to be far enough away that the simulated bogus drag cancels the pause. The coordinates are encoded into the lo/high bits of the lparam value.

What I can't wrap my head around is that the lparam from WM_NCLBUTTONDOWN shouldn't even be valid for the WM_MOUSEMOVE event. The lparam value of WM_MOUSEMOVE is the (x, y) coordinates of the client area, where as the WM_NCLBUTTONDOWN lparam is the (x, y) in screen coordinates. I really don't know why passing in the lparam from WM_NCLBUTTONDOWN doesn't also cancel the pause. I tested other lparam values for the dummy event with mixed results. Passing in !lparam would cancel the pause, where as a value that was only marginally different would not cancel it. (e.g. lparam + 1).

In summary, this is absolutely a hacky work-around :)

The actual robust and generally accepted solution is to execute your simulation and rendering logic from a different thread.

@madsmtm
Copy link
Member

madsmtm commented Mar 10, 2025

Thanks a lot for the context! I'd be okay with merging this if you included basically the block of text you wrote here as a code comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B - bug Dang, that shouldn't have happened DS - windows
Development

Successfully merging this pull request may close these issues.

[Windows] Pressing mouse in the window title bar freezes redraws for a short delay
2 participants