Mouse Cursor not changing until moved

I’m working on implementing dragging with a mouse. Here is the code that I am using to change the mouse cursor depending on the mouse button (in my PlayerController derived class):

void AArenaGamePlayerController::OnMousePress()
{
	CurrentMouseCursor = DragMouse;
}

void AArenaGamePlayerController::OnMouseReleased()
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("PC OnMouseReleased ") );
	CurrentMouseCursor = NormalMouse;
}

What I find is that when I hold the LMB down, the cursor changes as expected. However when I release the mouse button, and keep the pointer still, the cursor doesn’t change. It only changes when I move it a pixel. I can see the debug message on the screen, so I 'm confident the code is being called. I have even tried moving the code into the PlayerTick method with exactly the same results.

Does anyone know how I can force the mouse cursor to update on screen?

I have the same problem.

I think I know why, though I don’t know how to fix it. :frowning:

We only set a value in the PlayerController’s value structure without the aid of a function. That means that whatever is set can only be retrieved if
a) another signal will pump a new message into the game’s event queue and retrieve your value (hence the need for something to detect the new value and set a flag for the next round to react on this flag; or,
b) the game queue is not finished yet and somewhere, something in the bottom of the engine will pick up the new value.

After tracing the whole message queue (yea, about a day or so), I found that neither events are happening. Our derived classes are very low in the food chain and nothing picks up the value we’ve set unless, like you mentioned, we create an additional event like moving the mouse which will get the new cursor value.

The culprit is located in UGameViewportClient::GetCursor() which is called by FSceneViewport::OnCursorQuery();
the cursor value it gets is earlier that anything we set on the game level. It retrieves the last value set prior to raising the mouse button and never comes back unless another signal is sent.

I’ve also noticed that when we keep the mouse button down, FSceneViewport::OnCursorQuery() is fired repetitively although a single message for LMB::IE_Pressed is sent in your application. I think the change between the normal arrow and the hand is delayed the same way, but because it is fired repetitively, the change occurs only the second time around, at 1/60th of a second.

The solution is that @Epic should provide some method to call when we change the cursor so that it triggers some flag that asks to re-read the cursor again, instead of simply letting us set a value. There maybe is one, but it’s not clear in any documentation.

Regards.

This is also a problem when the game switches to cursor on and off. See : https://answers.unrealengine.com/questions/213389/mouse-focus-issues-when-hidingshowing-pointer.html

Any chance of a fix ?

any updates on this? it is causing some issues for our project as well!

I had the same problem and found a hacky fix by simulating mouse movement.

I added a variable to my custom player controller:

 EMouseCursor::Type DesiredMouseCursor;

And added this code to the PlayerTick function:

	// UE4 Hack: The cursor change doesn't happen until the mouse is moved
	// As a workaround, simulate some mouse movement.
	// Make sure we only do this once per frame, otherwise we can create lots of
	// unnecessary pointer events which are more likely to cause noticeable mouse jitter.
	if (CurrentMouseCursor != DesiredMouseCursor)
	{
		CurrentMouseCursor = DesiredMouseCursor;

		auto& App = FSlateApplication::Get();
		FVector2D CursorPos = App.GetCursorPos();
		App.SetCursorPos(CursorPos + FVector2D(0, 1));
		App.OnMouseMove();
		App.SetCursorPos(CursorPos);
		App.OnMouseMove();
	}

Then to change the cursor I assign to DesiredMouseCursor instead of CurrentMouseCursor.

This is a dirty hack and has only been tested on Windows 7, but it might be useful to someone until there’s an actual fix. From what I’ve read it looks like Linux requires a click rather than a move (and faking clicks could obviously cause some problems).

Unfortunately this doesn’t work here on 4.8 preview, Windows 8.

Hiding the cursor through DesiredMouseCursor will still require a click to get mouse inputs, and Slate hover events will still require a click after showing the cursor. Same behavior as before.

FYI this was acknowledged to be a UE bug and is in the known bugs list for 4.8P4 - hopefully we get answers soon.

It seems this is still an issue in 4.8.3, we experience the same problem in our project. Are there any updates on this issue?

Still an issue in 4.9

This is still an issue in 4.11.2

auto& App = FSlateApplication::Get();
FVector2D CursorPos = App.GetCursorPos();
App.SetCursorPos(CursorPos + FVector2D(0, 1));
App.OnMouseMove();
App.SetCursorPos(CursorPos);
App.OnMouseMove();

Great work in 4.11.2. Thanks a lot!

Hack for BP users :

3 Likes

Solution on 4.19.2 was

 auto& App = FSlateApplication::Get();
 App.QueryCursor(); //This line is refreshing the cursor (it executes fake mouse event for each platform).
1 Like

The problem is related to the focus.

I had the same problem when showing/hidding the cursor.

Try to put back the focus to the game viewport and the cursor should be reflected.

// Sets back the focus to the game viewport
FSlateApplication::Get().SetAllUserFocusToGameViewport();

I fixed my issue by using both ColdSteel48 and domzorg’s solutions. Thanks for that!

auto& App = FSlateApplication::Get();
App.SetAllUserFocusToGameViewport();
App.QueryCursor();

Crazy that this is needed though.

2 Likes

For people still wondering about this and getting some error when using FSlateApplication, and are working in newer versions of unreal (I’m working in UE5 EA), you need to go in the .Build.cs file and uncomment or add this:
PrivateDependencyModuleNames.AddRange(new string[] { “Slate”, “SlateCore” });

1 Like

This worked for me as well.


This works too. Idk if it’s a good solution though

firstly, thanks all of you, Same thing still occurs in UE5.0

I’ve struggled to find this post and tried some solution.

Issue

Trying to find a way to set a mouse cursor of a controller,
but the cursor does not change even when the CurrentMouseCursor’s value is changed correctly.(Need a click or some event to make the cursor change in the viewport…)

What I found

  1. There are some other post saying about this(pls refer to Reference)
  2. Happens to find that UWidgetBlueprintLibrary has a function does the exactly same thing.(Which can be called from BP&&Cpp without additional dependency)

Reference

  1. void UWidgetBlueprintLibrary::SetFocusToGameViewport() { FSlateApplication::Get().SetAllUserFocusToGameViewport(); }
  2. setting CurrentMouseCursor only works after a mouse click

I haven’t had any luck getting the cursor to update when calling that BP function. Do you have an example of how to set this up?