4k 28" Fullscreen reporting as 1440p

I recently got a new 4k monitor, and have it running alongside my old 1080p 26" monitor. I’m not sure if the dual setup matters.

When I run my game on the 4k, SDL_GetDesktopDisplayMode reports a window height of 1440. I tried swapping it out for SDL_GetCurrentDisplayMode, but it still reports 1440.

I did a little Googling and found a suggestion for a similar issue (not exactly the same; in this person’s case, he was creating a 1920x1080 window which was filling his 4k screen) that this is probably due to High DPI settings in Windows, which I thought might be worth a shot. I added SDL_WINDOW_ALLOW_HIGHDPI to my init flags as so (this is Ada code):

if (SDL_Init(SDL_INIT_VIDEO or SDL_INIT_AUDIO or SDL_INIT_JOYSTICK or SDL_INIT_GAMECONTROLLER or SDL_WINDOW_ALLOW_HIGHDPI) < 0) then
    raise SDL_Init_Failed; --this is a custom Exception
end if;

Still reporting 1440. Am I missing something? I’ve seen some other topics here suggesting High DPI support is still in the works, but I’m not sure that’s even the problem and also those topics were kind of old so I don’t know if that’s been completed yet.

Thanks!

SDL2 still doesn’t support HighDPI on Windows.

As a workaround you can call the WinAPI functions to tell Windows that your applications is “DPI-Aware” (which just means “Yes, I really want a window of the size I asked for with the actual native resolution, and I’ll scale things in my UI up myself if necessary”).
SDL_GetDesktopDisplayMode resolution reported in Windows 10 when using app scaling - #4 by Eric_Wasylishen has example code for this (loading the corresponding function dynamically so the code still works on older windows versions that don’t support them). Of course that’s in C, but I assume that it’s possible to do the same in Ada. Call that code before creating a window (I usually call it quite early in main(), before calling SDL_Init())

Ah, I see. I’ve never been a big fan of calling OS APIs directly, so I did a little more digging on other methods to achieve this same functionality. Turns out, you can actually specify this in a manifest, and to make it even better, you can embed your manifest as a resource. First you make the manifest:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"  ​xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
   ​<asmv3:application>
       ​<asmv3:windowsSettings>
           ​<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
       ​</asmv3:windowsSettings>
   ​</asmv3:application>
​</assembly>

I don’t really know what most of those element names are for. I just copy/pasted this from some Microsoft documentation and saw what I could trim down, which as it turns out, is almost nothing. Conventionally, you would save this as your exe name with .manifest at the end (for example, game.exe.manifest) and put it in the same directory as the exe, and it should work. But if you want to embed it, you can save it as whatever you want. I moved mine up a level and named it manifest.xml. Then in your resource file, make sure you #include <winuser.h> and add the line

1 RT_MANIFEST "filename"

In my case, the filename was “…\manifest.xml”. Worked beautifully.

If you don’t already have a resource file, I haven’t tested this by itself, but here’s a trimmed down example:

#include <winuser.h>   
​#ifdef RC_INVOKED
    ​1 RT_MANIFEST "..\\manifest.xml"
​#endif

Then you build with

windres -i myresource.rc -o myresource.o

And you link it just like any other object file.

3 Likes