Skip to content

Commit

Permalink
Platform: implement physical DPI scaling in Sdl2App on Windows.
Browse files Browse the repository at this point in the history
Yes, because it's exactly the other way for SDL. You know, consistency
and all. FFS.
  • Loading branch information
mosra committed Feb 15, 2020
1 parent 444b925 commit c3878c9
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 11 deletions.
6 changes: 4 additions & 2 deletions doc/changelog.dox
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,10 @@ See also:
enabled by default on macOS 10.15+ and iOS 13+. Applications running on
these platforms no longer need to supply a custom `Info.plist` in order to
enable HiDPI. See @ref platforms-macos-hidpi for more information.
- Implemented virtual DPI scaling in @ref Platform::GlfwApplication (was
behaving like physical before) (see [mosra/magnum#243](https://github.com/mosra/magnum/issues/243))
- Implemented virtual DPI scaling in @ref Platform::GlfwApplication on
Windows (was behaving like physical before) and physical DPI scaling in
@ref Platform::Sdl2Application (which was behaving like virtual before)
(see [mosra/magnum#243](https://github.com/mosra/magnum/issues/243))

@subsubsection changelog-latest-changes-trade Trade library

Expand Down
41 changes: 32 additions & 9 deletions src/Magnum/Platform/Sdl2Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@
#include "Magnum/Platform/GLContext.h"
#endif

#if defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)
/* For physical DPI scaling */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif

namespace Magnum { namespace Platform {

namespace {
Expand Down Expand Up @@ -224,7 +232,8 @@ Vector2 Sdl2Application::dpiScaling(const Configuration& configuration) {
/* Try to get virtual DPI scaling first, if supported and requested */
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_ANDROID)
if(dpiScalingPolicy == Implementation::Sdl2DpiScalingPolicy::Virtual) {
/* Use Xft.dpi on X11 */
/* Use Xft.dpi on X11, because SDL_GetDisplayDPI() returns the useless
physical value on Linux, while the virtual value on Windows. */
#ifdef _MAGNUM_PLATFORM_USE_X11
const Vector2 dpiScaling{Implementation::x11DpiScaling()};
if(!dpiScaling.isZero()) {
Expand All @@ -237,9 +246,7 @@ Vector2 Sdl2Application::dpiScaling(const Configuration& configuration) {
https://github.com/spurious/SDL-mirror/blob/17af4584cb28cdb3c2feba17e7d989a806007d9f/src/video/windows/SDL_windowsmodes.c#L266
and GetDpiForMonitor() returns 96 if the application is DPI unaware.
So we instead check for DPI awareness first (and tell the user if
not), and only if the app is, then we use SDL_GetDisplayDPI(). If
it's for some reason desired to get the DPI value unconditionally,
the user should use physical DPI scaling instead. */
not), and only if the app is, then we use SDL_GetDisplayDPI(). */
#elif defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)
if(!Implementation::isWindowsAppDpiAware()) {
Warning{verbose} << "Platform::Sdl2Application: your application is not set as DPI-aware, DPI scaling won't be used";
Expand Down Expand Up @@ -273,11 +280,10 @@ Vector2 Sdl2Application::dpiScaling(const Configuration& configuration) {
Debug{verbose} << "Platform::Sdl2Application: physical DPI scaling" << dpiScaling.x();
return dpiScaling;

/* Take display DPI elsewhere. Enable only on Linux (where it gets the
usually very-off value from X11) and on non-RT Windows (where it takes
the UI scale value like with virtual DPI scaling, but without checking
for DPI awareness first). Also only since SDL 2.0.4. */
#elif (defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT))) && SDL_VERSION_ATLEAST(2, 0, 4)
/* Take a physical display DPI. On Linux it gets the (usually very off)
physical value from X11. Also only since SDL 2.0.4. */
#elif defined(CORRADE_TARGET_UNIX)
#if SDL_VERSION_ATLEAST(2, 0, 4)
Vector2 dpi;
if(SDL_GetDisplayDPI(0, nullptr, &dpi.x(), &dpi.y()) == 0) {
const Vector2 dpiScaling{dpi/96.0f};
Expand All @@ -286,8 +292,25 @@ Vector2 Sdl2Application::dpiScaling(const Configuration& configuration) {
}

Warning{} << "Platform::Sdl2Application: can't get physical display DPI, falling back to no scaling:" << SDL_GetError();
#else
Debug{verbose} << "Platform::Sdl2Application: sorry, physical DPI scaling only available on SDL 2.0.4+";
#endif
return Vector2{1.0f};

/* HOWEVER, on Windows it gets the virtual DPI scaling, which we don't
want, so we need to call Windows APIs directly instead. Consistency my
ass. Related bug report that will probably never get actually
implemented: https://bugzilla.libsdl.org/show_bug.cgi?id=2473 */
#elif defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)
HDC hDC = GetWindowDC(nullptr);
Vector2i monitorSize{GetDeviceCaps(hDC, HORZSIZE), GetDeviceCaps(hDC, VERTSIZE)};
SDL_DisplayMode mode;
CORRADE_INTERNAL_ASSERT(SDL_GetDesktopDisplayMode(0, &mode) == 0);
auto dpi = Vector2{Vector2i{mode.w, mode.h}*25.4f/Vector2{monitorSize}};
const Vector2 dpiScaling{dpi/96.0f};
Debug{verbose} << "Platform::Sdl2Application: physical DPI scaling" << dpiScaling;
return dpiScaling;

/* Not implemented otherwise */
#else
Debug{verbose} << "Platform::Sdl2Application: sorry, physical DPI scaling not implemented on this platform yet";
Expand Down

0 comments on commit c3878c9

Please sign in to comment.