fix(windows): release cursor clip on focus loss - #4654
Open
Saratii wants to merge 1 commit into
Open
Conversation
ClipCursor is global OS state that Windows does not reset when a window loses focus. A clip rect applied while the window was focused therefore stayed active after focus loss, keeping the cursor trapped in the unfocused window. Worse, set_cursor_grab(CursorGrabMode::None) could not release it either, because refresh_os_cursor skips all ClipCursor updates when the window is not focused. Fix by releasing the active clip in refresh_os_cursor when the window is unfocused and the clip lies within the window client area (i.e. it is the clip this window applied, not one belonging to the now-active application), and by refreshing cursor flags on WM_KILLFOCUS/WM_SETFOCUS so the clip is released on focus loss and reapplied on focus gain even if the application does not change the grab mode itself. Fixes the Windows half of bevyengine/bevy#22750. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
ClipCursoris global OS state that Windows does not reset when a window loses focus. A clip rect applied while the window was focused therefore stays active after focus loss, keeping the cursor trapped in the unfocused window. Applications cannot release it either:Window::set_cursor_grab(CursorGrabMode::None)has no effect while unfocused, becauserefresh_os_cursorskips allClipCursorupdates when the window is not focused.Reported downstream in bevyengine/bevy#22750 (confine on focus gain,
Noneon focus loss — the cursor stays trapped after pressing the Windows key).Fix
refresh_os_cursor: when the window is unfocused, release the active clip if it lies within the window's client area — i.e. it is the clip this window applied (Confined= client rect,Locked= 1px rect inside it). A clip set by the now-active application elsewhere is left untouched, which is why the focused-only gate existed in the first place.WM_KILLFOCUS/WM_SETFOCUS: refresh cursor flags so the clip is released on focus loss and reapplied on focus gain even if the application never changes the grab mode, matching grab behavior on other platforms.Note: during
WM_KILLFOCUS,GetActiveWindow()may in some message orderings still return the window; in that case the release happens on the next cursor-flag refresh (e.g. the application's ownset_cursor_grabcall or a cursor move) instead of immediately.Verified with the bevy reproduction from the linked issue on Windows 11: the cursor now frees on focus loss and re-confines on focus gain. A backport to
v0.30.xis available at https://github.com/Saratii/winit/tree/fix/win32-release-cursor-clip-on-focus-loss-v0.30.🤖 Generated with Claude Code