LockMouseToViewport not properly working

So, I’ve passed the last couple of hours looking for a way to fix this issue.

I’m developing a simple RTS game and, like many of those who reported similar issues, I’m coding (in C++) an edge scrolling camera using mouse position and Viewport size.

At first I tried to set the input mode in the player controller with the “lock to viewport” boolean value to true, but I bumped in the “Locking mouse to viewport fails after clicking inside the window” (which is marked as resolved by the way).

Then I tried to call LockMouseToViewport(true) from my HUD class like this:

/* Lock mouse to viewport */
	GetWorld()->GetGameViewport()->SetMouseLockMode(EMouseLockMode::LockAlways);
	GetWorld()->GetGameViewport()->Viewport->LockMouseToViewport(true);

Now the mouse is partially locked: when reaching the left/upper edge of the viewport (in PIE or in windowed mode), GetMousePosition() frequently returns false, as if the “lock calculation” took place after the GetMousePosition() call.

Furthermore I’m experiencing worse problems when I enter fullscreen mode (Alt + Enter): in fullscreen GetMousePosition() gives problems in the right/bottom edges as well.

This is the most similar issue I found on the web, though he stated that the problem occured only on Linux, whereas I’m running on Windows 10.

If anyone has a fix it would be very much appreciated.

EDIT: it seems to work fine in the PIE immersive mode

EDIT: Stupid Windows. My real problem was Windows DPI scaling messing everything up: I simply checked “disable scaling at high DPI values” (running on 2560 x 1440) in in the compatibility tab of the EpicGame launcher shortcut properties and now everything works flawlessly.

I started digging in the unreal source code and ended up with this WINAPI function called from FWindowCursor : public ICursor:

BOOL WINAPI ClipCursor(
  _In_opt_ const RECT *lpRect
);

Apparently UE4 source code is only responsible for providing the RECT.left/top/right/bottom values (taken from the viewport widget) and it’s entirely up to windows to lock the mouse inside the rectangle.

Anyway, calling UGameViewport::GetMousePosition(FVector2D &MousePosition) will return false if FSceneViewport::GetMousePos(FIntPoint& MousePosition, const bool bLocalPosition) (with bLocalPosition = true) returns X < 0 or Y < 0. It follows that I should be able to solve my problem using:

GetWorld()->GetGameViewport()->Viewport->GetMousePos(CursorPos, true);

instead of:

bool bHasMousePosition = GetWorld()->GetGameViewport()->GetMousePosition(MousePosition);