Disable LockMouseToViewport

And if I SetInputMode in MyPlayerController::Tick the first 100 Ticks, and the stop setting input mode, my cursor is not locked for the first 100 ticks (and my camera does not work), and then it get locked (and my camera works).

If you need to have clicking enabled in your game while also handling movement input and preventing the mouse cursor from being captured/hidden, you will have to work around a bug/limitation in the current version of UE4. I believe there are already tickets/bug reports related to this. UE4 has changed how it handles this kind of thing several times over the last few versions, so you will probably have to change your code again when they fix this problem in the future.

Here is how you could work around this problem right now:

void ReceiveMouseUp();

void AMyController::ReceiveMouseUp()
{
	// do stuff any stuff you want

	// ...

	FInputModeGameAndUI InputMode;
	InputMode.SetHideCursorDuringCapture(false);
	InputMode.SetLockMouseToViewport(false);
	SetInputMode(InputMode);
}

void AMyController::SetupInputComponent()
{
	Super::SetupInputComponent();

	// ... stuff ...

	auto& UpBinding = InputComponent->BindAction("MyMouseClickInputActionName", IE_Released, this, &AMyController::ReceiveMouseUp);
	UpBinding.bExecuteWhenPaused = true;

}

Well I need to receive mouse input while pressing my mouse button (mouse button + dragging = camera rotation). I tried something which did not work. I am thinking of having a custom mouse cursor (a sprite) at cursor position instead. The only problem is to have a sprite always facing the camera, but I will watch this tutorial and see if it works.

It seems that the mouse is always locked within the viewport when an action button is clicked (no matter if AMyPlayerController::bShowMouseCursor == true and GEngine->GameViewport->Viewport->LockMouseToViewport(false)).

A workaround is to move the cursor at the opposite side of the screen when it reaches one side.

In MyPawn::Tick():

   // HasMouseMoved is a FIntPoint of MyPawn to keep track of the state of the cursor. 
   // If it just moved, we should not move it again at the opposite side 
   // (otherwise the position will blink between to opposite sides)

    FViewport* Viewport = GEngine->GameViewport->Viewport;
    FIntPoint Size = Viewport->GetSizeXY();

    UE_LOG(LogTemp, Warning, TEXT("Mouse pos: %d, %d"), Viewport->GetMouseX(), Viewport->GetMouseY());
    UE_LOG(LogTemp, Warning, TEXT("Size: %s"), *Size.ToString());
    const int32 MARGIN = 5;

    if(HasMouseMoved.X == 1 && Viewport->GetMouseX() > MARGIN || HasMouseMoved.X == -1 && Viewport->GetMouseX() < Size.X - MARGIN)
    {
        HasMouseMoved.X = 0;
    }
    if(HasMouseMoved.Y == 1 && Viewport->GetMouseY() > MARGIN || HasMouseMoved.Y == -1 && Viewport->GetMouseY() < Size.Y - MARGIN)
    {
        HasMouseMoved.Y = 0;
    }

    if(HasMouseMoved.X != 1 && Viewport->GetMouseX() <= MARGIN)
    {
        Viewport->SetMouse(Size.X-1, Viewport->GetMouseY());
        HasMouseMoved.X = -1;
    }
    else if(HasMouseMoved.X != -1 && Viewport->GetMouseX() >= Size.X-MARGIN)
    {
        Viewport->SetMouse(0, Viewport->GetMouseY());
        HasMouseMoved.X = 1;
    }

    if(HasMouseMoved.Y != 1 && Viewport->GetMouseY() <= MARGIN)
    {
        Viewport->SetMouse(Viewport->GetMouseX(), Size.Y-1);
        HasMouseMoved.Y = -1;
    }
    else if(HasMouseMoved.Y != -1 && Viewport->GetMouseY() >= Size.Y-MARGIN)
    {
        Viewport->SetMouse(Viewport->GetMouseX(), 0);
        HasMouseMoved.Y = 1;
    }