How to get current screen size/resolution?

The event is actually static. So you can avoid accessing unsafe pointers:

FViewport::ViewportResizedEvent.AddUFunction(callbackBlueprintObj, bpFunctionName);
2 Likes

I think it is a good intention but the response was so formatted and sure of itself, yet you are right, it’s backwards.

Function Engine.PlayerController.GetViewportSize 0x0000025BF1CE6B40
Getting Viewport Size: 1920 1080 ← fullscreen/borderless 1920-1080
Function Engine.PlayerController.GetViewportSize 0x0000025BF1CE6B40
Getting Viewport Size: 1680 1050 ← windowed 1680-1050
It depends I guess but that was tested UE 4.23?

Let’s look at what it ‘actually’ is doing for a few minutes to clarify once and for all.

GetViewportSize does get the integer values of the viewport by window d3d or renderer.
GSystemResolution gets the actual system resolution established by the system at initialization of the engine.

Here is where the engine established GSystemResolution:

	// Set GSystemResolution now that we have the size.
	FDisplayMetrics DisplayMetrics;
	FDisplayMetrics::RebuildDisplayMetrics(DisplayMetrics);
	FSystemResolution::RequestResolutionChange(DisplayMetrics.PrimaryDisplayWidth,   DisplayMetrics.PrimaryDisplayHeight, EWindowMode::Fullscreen);

But what is RebuildDisplayMetrics? This differs across IOS, Android, Linux, and Windows. On Android it grabs the screen window rect (unknown if it is the full screen or not). On Windows it uses GetSystemMetrics(), so is the set monitor resolution. On IOS/MAC it gets the primary screen frame, which again is monitor resolution.

Inside RebuildDisplayMetrics for Windows (which is used in most cases):

    // Total screen size of the primary monitor
    OutDisplayMetrics.PrimaryDisplayWidth = ::GetSystemMetrics( SM_CXSCREEN );
    OutDisplayMetrics.PrimaryDisplayHeight = ::GetSystemMetrics( SM_CYSCREEN );

This is what gSystemResolution will be, so it is opposite what he said. If his monitor is multi or larger, it will set gSystemResolution.ResX = ::GetSystemMetrics( SM_CXSCREEN ), gSystemResolution.ResY = ::GetSystemMetrics( SM_CYSCREEN ), etc.

Then the size of his window viewport will be set based on size of the viewport being rendered.

Inside GameViewportClient::SetDisplayConfiguration, gSystemResolution is then used as a fallback value if the engine or viewport is not established yet, and it calls RequestResolutionChange with those, otherwise it uses the new viewport values and then sets engine window mode, etc. (There is also another engine check, if a windowed simply matched your fullscreen value, then it basically is defined as fullscreen.)

bool UGameViewportClient::SetDisplayConfiguration(const FIntPoint* Dimensions, EWindowMode::Type WindowMode)
{
if (Viewport == NULL || ViewportFrame == NULL)
{
return true;
}

UGameEngine* GameEngine = Cast<UGameEngine>(GEngine);

if (GameEngine)
{
	UGameUserSettings* UserSettings = GameEngine->GetGameUserSettings();

	UserSettings->SetFullscreenMode(WindowMode);

	if (Dimensions)
	{
		UserSettings->SetScreenResolution(*Dimensions);
	}

	UserSettings->ApplySettings(false);
}
else
{
	int32 NewX = GSystemResolution.ResX;
	int32 NewY = GSystemResolution.ResY;

	if (Dimensions)
	{
		NewX = Dimensions->X;
		NewY = Dimensions->Y;
	}

	FSystemResolution::RequestResolutionChange(NewX, NewY, WindowMode);
}

return true;
}

So thus, just get your viewportXY for your window sizes, and in some/most cases will match with your full screen value anyway. However GSystemResolution does not usually change, viewportXY can change. For example it will change on a call request to change video settings, window configuration or dimensions. So thus it is most accurate, in most cases… and you have the system resolution if needed, which in full-screen, will match in most cases.

For DSR which is sometimes enabled on higher end hardware, to zoom, or spam more pixel details at cost of lower frames, I believe viewport sizes will stay the same. This might confuse some people. Here is how you must calculate it if so, using max % from the current viewport res.

(e.g. do this once or on changes, (r.DynamicRes.MaxScreenPercentage/100.0f) * Viewport->X = DsrX; even though, ViewportX is still accurate for the view bounds, and no idea why you would need that).

See Dynamic Resolution | Unreal Engine Documentation

What about slate units? there’s viewport size, there’s resolution. slate widgets use NEITHER. widget layout is dependent on the viewport display dimensions measured in slate units. How do you find the screen size in slate units?