We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2396

Summary: OSX: In relative mouse mode, mouse buttons are lost after clicking on window title bar.
Product: SDL Reporter: Tim McDaniel <tmcdaniel>
Component: eventsAssignee: (disabled) Jørgen Tjernø <jorgen>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: critical    
Priority: P2    
Version: 2.0.1   
Hardware: All   
OS: Mac OS X (All)   
Attachments: Workaround
Don't apply relative mode when moving

Description Tim McDaniel 2014-02-13 21:00:23 UTC
Have an SDL window in windowed mode.
Activate relative mouse mode.
Cmd+Tab away from app.
Click on window title bar.

Can't move window.
Mouse cursor is frozen.
Mouse clicks are lost.
Comment 1 Sam Lantinga 2014-02-23 01:28:50 UTC
Hey Jorgen, when you have a chance, can you take a quick look at this?

Thanks!
Comment 2 (disabled) Jørgen Tjernø 2014-02-25 00:58:11 UTC
I can reproduce being unable to move the window and that mouse clicks are lost, but I don't know what you mean by "mouse cursor is frozen." I still see SDL_MOUSEMOTION events.
Comment 3 (disabled) Jørgen Tjernø 2014-02-25 01:40:36 UTC
The issue seems to be that we warp the mouse cursor to the center of the window as soon as we get keyboard focus, even if the user is trying to move the window. Not entirely sure why the button events are lost, but we can investigate that after.

The fix would be to only warp the mouse cursor *after* the window move event is done. I cannot seem to find a way to detect this though - there is a windowWillMove: (which happens when you mousedown on the title bar), and a windowDidMove: (which happens when you mouseup *or* at regular intervals.) Mouse-up events are not dispatched to our window.

While not a great solution, maybe if you give the window focus by trying to move it, we should leave the cursor alone until you move the cursor over the window itself (and not the title bar), at which point we warp it to the center?
Comment 4 Tim McDaniel 2014-02-25 05:23:12 UTC
Created attachment 1579 [details]
Workaround

Here's somewhat of a workaround patch.  I too could not find a way to definitively detect the end of a window move.  My hack is to delay the key-focus-gained event, wait for a mouse move event (and assume that the move is then done), and then allow the key-focus-gained event to happen.  This isn't pretty, and doesn't give me warm fuzzies, but it seems to work "OK".

Note: In the patch, ASL_SDL is simply a macro we define when building our SDL lib, to easily identify our SDL mods.
Comment 5 (disabled) Jørgen Tjernø 2014-02-26 01:41:46 UTC
(In reply to Tim McDaniel from comment #4)
> Created attachment 1579 [details]
> Workaround
> 
> Here's somewhat of a workaround patch.  I too could not find a way to
> definitively detect the end of a window move.  My hack is to delay the
> key-focus-gained event, wait for a mouse move event (and assume that the
> move is then done), and then allow the key-focus-gained event to happen. 
> This isn't pretty, and doesn't give me warm fuzzies, but it seems to work
> "OK".
> 
> Note: In the patch, ASL_SDL is simply a macro we define when building our
> SDL lib, to easily identify our SDL mods.

Here's a slightly cleaner fix for the same issue - we use the "mouse up" event from -[NSWindow sendEvent:] to approximate when the move is finished. Do you want to test this revision and see if it resolves the issue for you too, Tim?

https://hg.libsdl.org/SDL/rev/028ed8da2524
Comment 6 Tim McDaniel 2014-02-26 20:40:13 UTC
Great fix, thanks.  One case it does not handle well is this:

* Key-focused window, relative mouse mode.
* Cmd-Tab away from window.
* App responds to SDL_WINDOWEVENT_FOCUS_LOST event by turning off relative mouse mode.
* Try to move the window with the mouse.
* App responds to the immediate SDL_WINDOWEVENT_FOCUS_GAINED event by turning on relative mouse mode.
* Window stops moving, you can't move the window any more, mouse cursor is stuck until you let go of the mouse button.
* All is well after that.

I don't know if it's critical that relative mouse mode be on before Cmd-Tabbing away from the window and turning relative mode off in response to the focus lost event.  It's probably just the act of turning on relative mode in response to the focus gained event that causes the problem.  The thing that my patch did to avoid this is to delay the focus gained event till after the window move was finished.
Comment 7 (disabled) Jørgen Tjernø 2014-02-26 22:35:07 UTC
(In reply to Tim McDaniel from comment #6)
> Great fix, thanks.  One case it does not handle well is this:
> 
> * Key-focused window, relative mouse mode.
> * Cmd-Tab away from window.
> * App responds to SDL_WINDOWEVENT_FOCUS_LOST event by turning off relative
> mouse mode.
> * Try to move the window with the mouse.
> * App responds to the immediate SDL_WINDOWEVENT_FOCUS_GAINED event by
> turning on relative mouse mode.
> * Window stops moving, you can't move the window any more, mouse cursor is
> stuck until you let go of the mouse button.
> * All is well after that.
> 
> I don't know if it's critical that relative mouse mode be on before
> Cmd-Tabbing away from the window and turning relative mode off in response
> to the focus lost event.  It's probably just the act of turning on relative
> mode in response to the focus gained event that causes the problem.  The
> thing that my patch did to avoid this is to delay the focus gained event
> till after the window move was finished.

When you say "app responds", you mean that the app (and not SDL) handles SDL_WINDOWEVENT_FOCUS_GAINED by calling SDL_SetMouseRelativeMode(SDL_TRUE)? That's not needed - you should just leave relative mode on when the app loses focus. That should work well on all platforms. There might've been a bug in the past that required this, but SDL 2.x should have no such problems.
Comment 8 Tim McDaniel 2014-02-26 23:06:32 UTC
(In reply to Jørgen Tjernø from comment #7)
> When you say "app responds", you mean that the app (and not SDL) handles
> SDL_WINDOWEVENT_FOCUS_GAINED by calling SDL_SetMouseRelativeMode(SDL_TRUE)?
> That's not needed - you should just leave relative mode on when the app
> loses focus. That should work well on all platforms. There might've been a
> bug in the past that required this, but SDL 2.x should have no such problems.

Yes, I mean the app, not SDL.

Unfortunately, in our case, I can't really prevent the SDL_SetMouseRelativeMode(SDL_TRUE) in response to SDL_WINDOWEVENT_FOCUS_GAINED.  The focus-gained event gets passed on to other code layers whose behavior shouldn't be modified.  I can certainly live with your current fix, it gets 90% there anyway.  ;-)  I'll just have to modify it a bit.
Comment 9 (disabled) Jørgen Tjernø 2014-02-26 23:12:10 UTC
Created attachment 1581 [details]
Don't apply relative mode when moving
Comment 10 (disabled) Jørgen Tjernø 2014-02-26 23:13:44 UTC
(In reply to Tim McDaniel from comment #8)
> (In reply to Jørgen Tjernø from comment #7)
> > When you say "app responds", you mean that the app (and not SDL) handles
> > SDL_WINDOWEVENT_FOCUS_GAINED by calling SDL_SetMouseRelativeMode(SDL_TRUE)?
> > That's not needed - you should just leave relative mode on when the app
> > loses focus. That should work well on all platforms. There might've been a
> > bug in the past that required this, but SDL 2.x should have no such problems.
> 
> Yes, I mean the app, not SDL.
> 
> Unfortunately, in our case, I can't really prevent the
> SDL_SetMouseRelativeMode(SDL_TRUE) in response to
> SDL_WINDOWEVENT_FOCUS_GAINED.  The focus-gained event gets passed on to
> other code layers whose behavior shouldn't be modified.  I can certainly
> live with your current fix, it gets 90% there anyway.  ;-)  I'll just have
> to modify it a bit.

If you try the latest patch attached to this bug, does that solve it?

Basically it makes Cocoa_SetRelativeMouseMode() not call CGAssociateMouseAndMouseCursorPosition() if we're in the process of moving a window, with the assumption that the mouse relative mode will be applied once the window finishes moving / gets focus. We could even do the early out if SDL_GetMouseFocus() returns NULL.
Comment 11 Tim McDaniel 2014-02-27 00:05:30 UTC
(In reply to Jørgen Tjernø from comment #10)
> If you try the latest patch attached to this bug, does that solve it?
> 
> Basically it makes Cocoa_SetRelativeMouseMode() not call
> CGAssociateMouseAndMouseCursorPosition() if we're in the process of moving a
> window, with the assumption that the mouse relative mode will be applied
> once the window finishes moving / gets focus. We could even do the early out
> if SDL_GetMouseFocus() returns NULL.

That patch does work pretty well.
Comment 12 (disabled) Jørgen Tjernø 2014-02-27 00:12:36 UTC
Okay, if there are no more issues with this behavior, I'm considering this bug fixed.

Committed as https://hg.libsdl.org/SDL/rev/acc0dcf38b3d

Thanks for the report & help in fixing it!
Comment 13 Tim McDaniel 2014-02-27 00:23:04 UTC
(In reply to Jørgen Tjernø from comment #12)
> Okay, if there are no more issues with this behavior, I'm considering this
> bug fixed.
> 
> Committed as https://hg.libsdl.org/SDL/rev/acc0dcf38b3d
> 
> Thanks for the report & help in fixing it!

In that commit, you forgot a value for the second return statement.
Thanks!
Comment 14 (disabled) Jørgen Tjernø 2014-02-27 00:28:12 UTC
Haha, whoops, thanks for the catch. I wonder why buildbot didn't email me.