UE4.16.3 Packaged game cursor not show up unless players re-focus window manually (partially solved)

After setting up hardware cursor asset path via project setting > User Interface > Hardware Cursors, the hardware cursor shows up fine in PIE, however, in package build, the cursor will not show unless I re-focus (alt-tab twice) the game window manually.

I’ve searched on net and found people with similar issues, who solved the problem by calling SetInputModeUIOnly node during game initialization. I’ve adopted the same method, but sadly, the solution didn’t work for me:

https://i.gyazo.com/0190d1aea951e81cfdfd91604ad712ab.png

I’ve then tried calling this function when the user press the “start” button in the launch menu, but the hardware cursor still did not show up.

I’ve then searched through the engine C++ code, and found out the SetHardwareCursor() is blocked by this flag: bIsMouseOverClient, which is default to false and set to true only when MouseEnter() is called.

The whole code looks like this:



bool UGameViewportClient::SetHardwareCursor(EMouseCursor::Type CursorShape, FName GameContentPath, FVector2D HotSpot)
{
    TSharedPtr<FHardwareCursor> HardwareCursor = HardwareCursorCache.FindRef(GameContentPath);
    if ( HardwareCursor.IsValid() == false )
    {
        HardwareCursor = MakeShared<FHardwareCursor>(FPaths::GameContentDir() / GameContentPath.ToString(), HotSpot);
        if ( HardwareCursor->GetHandle() == nullptr )
        {
            return false;
        }

        HardwareCursorCache.Add(GameContentPath, HardwareCursor);
    }

    HardwareCursors.Add(CursorShape, HardwareCursor);

    if ( bIsMouseOverClient )
    {
        TSharedPtr<ICursor> PlatformCursor = FSlateApplication::Get().GetPlatformCursor();
        if ( ICursor* Cursor = PlatformCursor.Get() )
        {
            Cursor->SetTypeShape(CursorShape, HardwareCursor->GetHandle());
        }
    }

    return true;
}


I decided to simply comment out the if ( bIsMouseOverClient ) in the source code, and now my hardware cursor shows up without me manually re-focusing the game window.

This seems to be a hacky approach to solve the problem, I’m wondering if there’s anyone who encounters a similar problem? and what is the “correct” way to solve the re-forucsing problem in packaged build?

Thank you!

This works for me in both PIE and package builds (Note: the custom cursors are in Content/Slate directory that is cooked always) and tested in UE4.18+. I don’t know if it works in UE4.16.x.

In your player controller:


#include “Engine/LocalPlayer.h”
#include “Engine/GameViewportClient.h”

AYourPlayerController::AYourPlayerController()
{

bShowMouseCursor = true;

}

void AYourPlayerController::BeginPlay()
{
Super::BeginPlay();

// set input mode
FInputModeGameAndUI NewInputMode = FInputModeGameAndUI();
NewInputMode.SetHideCursorDuringCapture(false);
SetInputMode(NewInputMode);

}

When you want to switch to a different cursor:

void AYourPlayerController::ChangeMouseCursor(EMouseCursor::Type NewMouseCursor)
{
// don’t switch if same cursor specified
if (CurrentMouseCursor == NewMouseCursor)
{
return;
}

ULocalPlayer* const LocalPlayer = Cast&lt;ULocalPlayer&gt;(Player);
if (LocalPlayer && LocalPlayer-&gt;ViewportClient)
{
    FViewport* Viewport = LocalPlayer-&gt;ViewportClient-&gt;Viewport;
    if (Viewport)
    {
        CurrentMouseCursor = NewMouseCursor;
        Viewport-&gt;UpdateMouseCursor(true);
    }
}

}

Maybe this helps.

Hi NikosKK,

Thank you for your reply.

I’ll test this solution out after I re-organize my code, it’s good to know the solution already works in both PIE and packaged build though!

Thank you again and have a productive day! :smiley: