Fix #134818: macOS: Hidden mouse grab not keeping mouse in window

This commit fixes an issue where WM cursor grabbing, when used
in "hidden" mode (`GHOST_kGrabHide`) would unexpectedly not prevent the
cursor from escaping the Blender window and revealing itself when
hovering over macOS desktop elements like the application Dock.

Looking at the original issue in past Blender versions, testing with the
Walk Navigation operator, this used to work in Blender 3.2, and broke
in Blender 3.3. Bisecting leads to commit 4c4e8cc926 (Fix T99021:
Walk-mode doesn't work in Wayland), which switched the Walk Navigation
mouse warping method from custom `WM_cursor_warp` logic to using
`WM_cursor_grab_{enable/disable}`.

Then, looking at the WM_cursor_grab Cocoa implementation, more
especially at the `GHOST_kGrabHide` case in `handleMouseEvent`, a
comment ("Cursor hidden grab operation : no cursor move") suggests that
hiding the cursor would previously prevent it from moving (possibly in
earlier macOS versions?).

This fix, the simplest I could come up with other than implementing
simple window warping for the `GHOST_kGrabHide` case (similar to what's
done on Windows, see #113066) is to use
`CGAssociateMouseAndMouseCursorPosition` to disable cursor movements
for the duration of the hidden grab, effectively restoring the original
behavior indicated in the comment.

Pull Request: https://projects.blender.org/blender/blender/pulls/148007
This commit is contained in:
Jonas Holzman
2025-10-14 14:31:02 +02:00
parent 084f04ec09
commit e6064b2be3

View File

@@ -1187,6 +1187,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode
setCursorGrabAccum(0, 0);
if (mode == GHOST_kGrabHide) {
/* Dissociate cursor movements from the mouse while hidden to prevent the cursor from
* being accidentally revealed whe hovering over desktop elements like the Dock. */
CGAssociateMouseAndMouseCursorPosition(false);
setWindowCursorVisibility(false);
}
@@ -1198,6 +1202,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode
else {
if (cursor_grab_ == GHOST_kGrabHide) {
system_cocoa_->setCursorPosition(cursor_grab_init_pos_[0], cursor_grab_init_pos_[1]);
CGAssociateMouseAndMouseCursorPosition(true);
setWindowCursorVisibility(true);
}