I’ve done a lot more research. Noisycat posted a solution:
target stop-hook add --one-liner "p ::UngrabAllInputImpl()"
Unfortunately, that didn’t work for me, so I investigated further. Unreal on Linux is layered on top of SDL. There are at least two things in SDL that can capture the mouse:
-
SDL_CaptureMouse(SDL_TRUE). Unreal calls this function in a few situations.
-
SDL_HINT_MOUSE_AUTO_CAPTURE. This is enabled by default. Whenever you generate a mouse-down event, SDL auto-captures the mouse. If it didn’t do this, then if you clicked the mouse inside the Unreal window, then dragged the mouse to some other window, and then released the mouse, then the mouse-down event would go to the Unreal window, but the mouse-up event would go to the other window. That would suck, because Unreal would think the mouse was still down.
Noisycat’s solution calls UngrabAllInputImpl, which is supposed to uncapture the mouse. It contains a call to SDL_CaptureMouse(SDL_FALSE), which is effective only if the mouse was captured by SDL_CaptureMouse(SDL_TRUE). But if the mouse was captured by SDL_HINT_MOUSE_AUTO_CAPTURE, then SDL_CaptureMouse(SDL_FALSE) has no effect.
So, if you hit a breakpoint at a moment when the mouse is down, then the mouse is going to be in a captured state. In this situation, Noisycat’s solution fails to uncapture the mouse. In my game, a click-and-drag action was triggering the breakpoint, so it was always in a bad state in the debugger.
Honestly, I don’t have a perfect solution, but I do have some experimental ones. You can turn off mouse-auto-capture entirely by inserting the following code into FLinuxPlatformApplicationMisc::InitSDL:
SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0");
So far, that’s been working reliably for me, when I use it in combination with Noisycat’s solution.
That could cause problems with mouse-up events going to the wrong window. So far, that hasn’t been a problem for me. Maybe Unreal already contains code to deal with this.
Here’s a different solution that didn’t work, but I don’t know why not:
target stop-hook add --one-liner "p ::SDL_UpdateMouseCapture(SDL_TRUE)"
That routine, SDL_UpdateMouseCapture, is an internal SDL routine. If the parameter is SDL_TRUE, then that forces a mouse uncapture, regardless of whether the mouse was captured by SDL_CaptureMouse or SDL_HINT_MOUSE_AUTO_CAPTURE. In my experience so far, this seems to work some of the time, but definitely not all of the time.
In theory, I like the second solution better, because it doesn’t mess with Unreal’s normal behavior. But sadly, it didn’t work. Maybe you can continue my research and figure out how to make it work. If you do, please followup here. I’d like to know the solution.
By the way, you can put a “target stop-hook” command into lldbinit, but instead, you can put it into your code-workspace, in the launch configuration initCommands. Doing this avoids the need for Noisycat’s python wrapper.
Thanks for Noisycat for doing the research that led up to this!