Browse Source

Platform: initial HiDPI support in GlfwApplication.

Not basing this off GLFW 3.3 as it's far from being released yet, just a
copy of what's done for SDL2 already.
pull/280/head
Vladimír Vondruš 8 years ago
parent
commit
dba35bac7a
  1. 2
      doc/changelog.dox
  2. 11
      modules/FindMagnum.cmake
  3. 23
      src/Magnum/Platform/CMakeLists.txt
  4. 127
      src/Magnum/Platform/GlfwApplication.cpp
  5. 190
      src/Magnum/Platform/GlfwApplication.h
  6. 16
      src/Magnum/Platform/Sdl2Application.cpp
  7. 8
      src/Magnum/Platform/Sdl2Application.h

2
doc/changelog.dox

@ -92,7 +92,7 @@ See also:
@subsubsection changelog-latest-new-platform Platform libraries @subsubsection changelog-latest-new-platform Platform libraries
- Initial HiDPI support for Linux and Emscripten in - Initial HiDPI support for Linux and Emscripten in
@ref Platform::Sdl2Application @ref Platform::Sdl2Application and @ref Platform::GlfwApplication
- Implemented missing resize event support in @ref Platform::Sdl2Application - Implemented missing resize event support in @ref Platform::Sdl2Application
on @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten" on @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten"
- Ability to modify CSS classes that control layout of - Ability to modify CSS classes that control layout of

11
modules/FindMagnum.cmake

@ -622,6 +622,17 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
find_package(GLFW) find_package(GLFW)
set_property(TARGET Magnum::${_component} APPEND PROPERTY set_property(TARGET Magnum::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES GLFW::GLFW) INTERFACE_LINK_LIBRARIES GLFW::GLFW)
# Use the Foundation framework on Apple to query the DPI awareness
if(CORRADE_TARGET_APPLE)
find_library(_MAGNUM_APPLE_FOUNDATION_FRAMEWORK_LIBRARY Foundation)
mark_as_advanced(_MAGNUM_APPLE_FOUNDATION_FRAMEWORK_LIBRARY)
set_property(TARGET Magnum::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${_MAGNUM_APPLE_FOUNDATION_FRAMEWORK_LIBRARY})
# Needed for opt-in DPI queries
elseif(CORRADE_TARGET_UNIX)
set_property(TARGET Magnum::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS})
endif()
# With GLVND (since CMake 3.11) we need to explicitly link to # With GLVND (since CMake 3.11) we need to explicitly link to
# GLX/EGL because libOpenGL doesn't provide it. For EGL we have # GLX/EGL because libOpenGL doesn't provide it. For EGL we have

23
src/Magnum/Platform/CMakeLists.txt

@ -125,6 +125,9 @@ if(WITH_GLFWAPPLICATION)
if(TARGET_GL) if(TARGET_GL)
list(APPEND MagnumGlfwApplication_SRCS ${MagnumSomeContext_OBJECTS}) list(APPEND MagnumGlfwApplication_SRCS ${MagnumSomeContext_OBJECTS})
endif() endif()
if(CORRADE_TARGET_APPLE)
list(APPEND MagnumGlfwApplication_SRCS Implementation/dpiScaling.mm)
endif()
add_library(MagnumGlfwApplication STATIC add_library(MagnumGlfwApplication STATIC
${MagnumGlfwApplication_SRCS} ${MagnumGlfwApplication_SRCS}
@ -142,6 +145,26 @@ if(WITH_GLFWAPPLICATION)
${MagnumSomeContext_LIBRARY}) ${MagnumSomeContext_LIBRARY})
endif() endif()
# Use the Foundation framework on Apple to query the DPI awareness
if(CORRADE_TARGET_APPLE)
find_library(_MAGNUM_APPLE_FOUNDATION_FRAMEWORK_LIBRARY Foundation)
mark_as_advanced(_MAGNUM_APPLE_FOUNDATION_FRAMEWORK_LIBRARY)
find_path(_MAGNUM_APPLE_FOUNDATION_FRAMEWORK_INCLUDE_DIR NAMES NSBundle.h)
mark_as_advanced(_MAGNUM_APPLE_FOUNDATION_FRAMEWORK_INCLUDE_DIR)
target_link_libraries(MagnumGlfwApplication PUBLIC ${_MAGNUM_APPLE_FOUNDATION_FRAMEWORK_LIBRARY})
target_include_directories(MagnumGlfwApplication PRIVATE ${_MAGNUM_APPLE_FOUNDATION_FRAMEWORK_INCLUDE_DIR})
# If there is X11, ask it for DPI
elseif(CORRADE_TARGET_UNIX)
find_package(X11)
if(X11_FOUND)
# Not linking to X11, we dlopen() instead
target_include_directories(MagnumGlfwApplication PRIVATE ${X11_X11_INCLUDE_PATH})
target_link_libraries(MagnumGlfwApplication PUBLIC ${CMAKE_DL_LIBS})
target_compile_definitions(MagnumGlfwApplication PRIVATE "_MAGNUM_PLATFORM_USE_X11")
endif()
endif()
install(FILES ${MagnumGlfwApplication_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(FILES ${MagnumGlfwApplication_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumGlfwApplication install(TARGETS MagnumGlfwApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}

127
src/Magnum/Platform/GlfwApplication.cpp

@ -32,6 +32,7 @@
#include <Corrade/Utility/Unicode.h> #include <Corrade/Utility/Unicode.h>
#include "Magnum/Platform/ScreenedApplication.hpp" #include "Magnum/Platform/ScreenedApplication.hpp"
#include "Magnum/Platform/Implementation/dpiScaling.hpp"
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
#include "Magnum/GL/Version.h" #include "Magnum/GL/Version.h"
@ -59,10 +60,14 @@ GlfwApplication::GlfwApplication(const Arguments& arguments, const Configuration
GlfwApplication::GlfwApplication(const Arguments& arguments, NoCreateT): GlfwApplication::GlfwApplication(const Arguments& arguments, NoCreateT):
_flags{Flag::Redraw} _flags{Flag::Redraw}
{
Utility::Arguments args{Implementation::windowScalingArguments()};
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
, _context{new GLContext{NoCreate, arguments.argc, arguments.argv}} _context.reset(new GLContext{NoCreate, args, arguments.argc, arguments.argv});
#else
args.parse(arguments.argc, arguments.argv);
#endif #endif
{
/* Init GLFW */ /* Init GLFW */
glfwSetErrorCallback([](int, const char* const description) { glfwSetErrorCallback([](int, const char* const description) {
Error{} << description; Error{} << description;
@ -73,9 +78,24 @@ GlfwApplication::GlfwApplication(const Arguments& arguments, NoCreateT):
std::exit(8); std::exit(8);
} }
#ifndef MAGNUM_TARGET_GL /* Save command-line arguments */
static_cast<void>(arguments); if(args.value("log") == "verbose") _verboseLog = true;
const std::string dpiScaling = args.value("dpi-scaling");
if(dpiScaling == "default")
_commandLineDpiScalingPolicy = Implementation::GlfwDpiScalingPolicy::Default;
#ifdef CORRADE_TARGET_APPLE
else if(dpiScaling == "framebuffer")
_commandLineDpiScalingPolicy = Implementation::GlfwDpiScalingPolicy::Framebuffer;
#else
else if(dpiScaling == "virtual")
_commandLineDpiScalingPolicy = Implementation::GlfwDpiScalingPolicy::Virtual;
else if(dpiScaling == "physical")
_commandLineDpiScalingPolicy = Implementation::GlfwDpiScalingPolicy::Physical;
#endif #endif
else if(dpiScaling.find_first_of(" \t\n") != std::string::npos)
_commandLineDpiScaling = args.value<Vector2>("dpi-scaling");
else
_commandLineDpiScaling = Vector2{args.value<Float>("dpi-scaling")};
} }
void GlfwApplication::create() { void GlfwApplication::create() {
@ -92,6 +112,82 @@ void GlfwApplication::create(const Configuration& configuration, const GLConfigu
} }
#endif #endif
Vector2 GlfwApplication::dpiScaling(const Configuration& configuration) const {
std::ostream* verbose = _verboseLog ? Debug::output() : nullptr;
/* Print a helpful warning in case some extra steps are needed for HiDPI
support */
#ifdef CORRADE_TARGET_APPLE
if(!Implementation::isAppleBundleHiDpiEnabled())
Warning{} << "Platform::GlfwApplication: warning: the executable is not a HiDPI-enabled app bundle";
#elif defined(CORRADE_TARGET_WINDOWS)
/** @todo */
#endif
/* Use values from the configuration only if not overriden on command line.
In any case explicit scaling has a precedence before the policy. */
Implementation::GlfwDpiScalingPolicy dpiScalingPolicy{};
if(!_commandLineDpiScaling.isZero()) {
Debug{verbose} << "Platform::GlfwApplication: user-defined DPI scaling" << _commandLineDpiScaling.x();
return _commandLineDpiScaling;
} else if(UnsignedByte(_commandLineDpiScalingPolicy)) {
dpiScalingPolicy = _commandLineDpiScalingPolicy;
} else if(!configuration.dpiScaling().isZero()) {
Debug{verbose} << "Platform::GlfwApplication: app-defined DPI scaling" << _commandLineDpiScaling.x();
return configuration.dpiScaling();
} else {
dpiScalingPolicy = configuration.dpiScalingPolicy();
}
/* There's no choice on Apple, it's all controlled by the plist file. So
unless someone specified custom scaling via config or command-line
above, return the default. */
#ifdef CORRADE_TARGET_APPLE
return Vector2{1.0f};
/* Otherwise there's a choice between virtual and physical DPI scaling */
#else
/* Try to get virtual DPI scaling first, if supported and requested */
if(dpiScalingPolicy == Implementation::GlfwDpiScalingPolicy::Virtual) {
/* Use Xft.dpi on X11 */
#ifdef _MAGNUM_PLATFORM_USE_X11
const Vector2 dpiScaling{Implementation::x11DpiScaling()};
if(!dpiScaling.isZero()) {
Debug{verbose} << "Platform::GlfwApplication: virtual DPI scaling" << dpiScaling.x();
return dpiScaling;
}
/* Otherwise ¯\_(ツ)_/¯ */
#else
Debug{verbose} << "Platform::GlfwApplication: sorry, virtual DPI scaling not implemented on this platform yet";
return Vector2{1.0f};
#endif
}
/* At this point, either the virtual DPI query failed or a physical DPI
scaling is requested */
CORRADE_INTERNAL_ASSERT(dpiScalingPolicy == Implementation::GlfwDpiScalingPolicy::Virtual || dpiScalingPolicy == Implementation::GlfwDpiScalingPolicy::Physical);
/* Take display DPI. Enable only on Linux for now, I need to test this
properly on Windows first. */
#ifdef CORRADE_TARGET_UNIX
GLFWmonitor* const monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* const mode = glfwGetVideoMode(monitor);
Vector2i monitorSize;
glfwGetMonitorPhysicalSize(monitor, &monitorSize.x(), &monitorSize.y());
auto dpi = Vector2{Vector2i{mode->width, mode->height}*25.4f/Vector2{monitorSize}};
const Vector2 dpiScaling{dpi/96.0f};
Debug{verbose} << "Platform::GlfwApplication: physical DPI scaling" << dpiScaling;
return dpiScaling;
/* Not implemented otherwise */
#else
Debug{verbose} << "Platform::GlfwApplication: sorry, physical DPI scaling not implemented on this platform yet";
return Vector2{1.0f};
#endif
#endif
}
bool GlfwApplication::tryCreate(const Configuration& configuration) { bool GlfwApplication::tryCreate(const Configuration& configuration) {
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
#ifdef GLFW_NO_API #ifdef GLFW_NO_API
@ -104,6 +200,10 @@ bool GlfwApplication::tryCreate(const Configuration& configuration) {
CORRADE_ASSERT(!_window, "Platform::GlfwApplication::tryCreate(): window already created", false); CORRADE_ASSERT(!_window, "Platform::GlfwApplication::tryCreate(): window already created", false);
/* Scale window based on DPI */
_dpiScaling = dpiScaling(configuration);
const Vector2i scaledWindowSize = configuration.size()*_dpiScaling;
/* Window flags */ /* Window flags */
GLFWmonitor* monitor = nullptr; /* Needed for setting fullscreen */ GLFWmonitor* monitor = nullptr; /* Needed for setting fullscreen */
if (configuration.windowFlags() >= Configuration::WindowFlag::Fullscreen) { if (configuration.windowFlags() >= Configuration::WindowFlag::Fullscreen) {
@ -126,7 +226,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration) {
#endif #endif
/* Create the window */ /* Create the window */
_window = glfwCreateWindow(configuration.size().x(), configuration.size().y(), configuration.title().c_str(), monitor, nullptr); _window = glfwCreateWindow(scaledWindowSize.x(), scaledWindowSize.y(), configuration.title().c_str(), monitor, nullptr);
if(!_window) { if(!_window) {
Error() << "Platform::GlfwApplication::tryCreate(): cannot create window"; Error() << "Platform::GlfwApplication::tryCreate(): cannot create window";
glfwTerminate(); glfwTerminate();
@ -194,6 +294,10 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf
CORRADE_ASSERT(!_window && _context->version() == GL::Version::None, "Platform::GlfwApplication::tryCreate(): window with OpenGL context already created", false); CORRADE_ASSERT(!_window && _context->version() == GL::Version::None, "Platform::GlfwApplication::tryCreate(): window with OpenGL context already created", false);
/* Scale window based on DPI */
_dpiScaling = dpiScaling(configuration);
const Vector2i scaledWindowSize = configuration.size()*_dpiScaling;
/* Window flags */ /* Window flags */
GLFWmonitor* monitor = nullptr; /* Needed for setting fullscreen */ GLFWmonitor* monitor = nullptr; /* Needed for setting fullscreen */
if (configuration.windowFlags() >= Configuration::WindowFlag::Fullscreen) { if (configuration.windowFlags() >= Configuration::WindowFlag::Fullscreen) {
@ -271,7 +375,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf
blinking in case we have to destroy it again right away. If the creation blinking in case we have to destroy it again right away. If the creation
succeeds, make the context current so we can query GL_VENDOR below. */ succeeds, make the context current so we can query GL_VENDOR below. */
glfwWindowHint(GLFW_VISIBLE, false); glfwWindowHint(GLFW_VISIBLE, false);
if((_window = glfwCreateWindow(configuration.size().x(), configuration.size().y(), configuration.title().c_str(), monitor, nullptr))) if((_window = glfwCreateWindow(scaledWindowSize.x(), scaledWindowSize.y(), configuration.title().c_str(), monitor, nullptr)))
glfwMakeContextCurrent(_window); glfwMakeContextCurrent(_window);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -312,7 +416,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, false); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, false);
_window = glfwCreateWindow(configuration.size().x(), configuration.size().y(), configuration.title().c_str(), monitor, nullptr); _window = glfwCreateWindow(scaledWindowSize.x(), scaledWindowSize.y(), configuration.title().c_str(), monitor, nullptr);
} }
#endif #endif
@ -433,6 +537,14 @@ Vector2i GlfwApplication::windowSize() const {
return size; return size;
} }
Vector2i GlfwApplication::framebufferSize() const {
CORRADE_ASSERT(_window, "Platform::GlfwApplication::framebufferSize(): no window opened", {});
Vector2i size;
glfwGetFramebufferSize(_window, &size.x(), &size.y());
return size;
}
void GlfwApplication::setSwapInterval(const Int interval) { void GlfwApplication::setSwapInterval(const Int interval) {
glfwSwapInterval(interval); glfwSwapInterval(interval);
} }
@ -518,6 +630,7 @@ GlfwApplication::Configuration::Configuration():
_title{"Magnum GLFW Application"}, _title{"Magnum GLFW Application"},
_size{800, 600}, _size{800, 600},
_windowFlags{WindowFlag::Focused}, _windowFlags{WindowFlag::Focused},
_dpiScalingPolicy{DpiScalingPolicy::Default},
_cursorMode{CursorMode::Normal} _cursorMode{CursorMode::Normal}
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
, _sampleCount{0}, _version{GL::Version::None} , _sampleCount{0}, _version{GL::Version::None}

190
src/Magnum/Platform/GlfwApplication.h

@ -51,6 +51,10 @@
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
namespace Implementation {
enum class GlfwDpiScalingPolicy: UnsignedByte;
}
/** @nosubgrouping /** @nosubgrouping
@brief GLFW application @brief GLFW application
@ -114,6 +118,13 @@ MAGNUM_GLFWAPPLICATION_MAIN(MyApplication)
If no other application header is included, this class is also aliased to If no other application header is included, this class is also aliased to
@cpp Platform::Application @ce and the macro is aliased to @cpp Platform::Application @ce and the macro is aliased to
@cpp MAGNUM_APPLICATION_MAIN() @ce to simplify porting. @cpp MAGNUM_APPLICATION_MAIN() @ce to simplify porting.
@section Platform-GlfwApplication-dpi DPI awareness
DPI awareness behavior is consistent with @ref Sdl2Application except that iOS
or Emscripten specifics don't apply here. See
@ref Platform-Sdl2Application-dpi "its DPI awareness documentation" for more
information.
*/ */
class GlfwApplication { class GlfwApplication {
public: public:
@ -336,11 +347,53 @@ class GlfwApplication {
* @brief Window size * @brief Window size
* *
* Window size to which all input event coordinates can be related. * Window size to which all input event coordinates can be related.
* Note that especially on HiDPI systems the reported window size might * Note that, especially on HiDPI systems, it may be different from
* not be the same as framebuffer size. * @ref framebufferSize(). Expects that a window is already created.
* See @ref Platform-GlfwApplication-dpi for more information.
* @see @ref dpiScaling()
*/ */
Vector2i windowSize() const; Vector2i windowSize() const;
#if defined(MAGNUM_TARGET_GL) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* @brief Framebuffer size
*
* Size of the default framebuffer. Note that, especially on HiDPI
* systems, it may be different from @ref windowSize(). Expects that a
* window is already created. See @ref Platform-GlfwApplication-dpi for
* more information.
*
* @note This function is available only if Magnum is compiled with
* @ref MAGNUM_TARGET_GL enabled (done by default). See
* @ref building-features for more information.
*
* @see @ref dpiScaling()
*/
Vector2i framebufferSize() const;
#endif
/**
* @brief DPI scaling
*
* How the content should be scaled relative to system defaults for
* given @ref windowSize(). If a window is not created yet, returns
* zero vector, use @ref dpiScaling(const Configuration&) const for
* calculating a value independently. See @ref Platform-GlfwApplication-dpi
* for more information.
* @see @ref framebufferSize()
*/
Vector2 dpiScaling() const { return _dpiScaling; }
/**
* @brief DPI scaling for given configuration
*
* Calculates DPI scaling that would be used when creating a window
* with given @p configuration. Takes into account DPI scaling policy
* and custom scaling specified on the command-line. See
* @ref Platform-GlfwApplication-dpi for more information.
*/
Vector2 dpiScaling(const Configuration& configuration) const;
protected: protected:
/** /**
* @brief Swap buffers * @brief Swap buffers
@ -499,6 +552,12 @@ class GlfwApplication {
void setupCallbacks(); void setupCallbacks();
/* These are saved from command-line arguments */
bool _verboseLog{};
Implementation::GlfwDpiScalingPolicy _commandLineDpiScalingPolicy{};
Vector2 _commandLineDpiScaling;
Vector2 _dpiScaling;
GLFWwindow* _window{nullptr}; GLFWwindow* _window{nullptr};
Flags _flags; Flags _flags;
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
@ -667,6 +726,29 @@ class GlfwApplication::GLConfiguration {
CORRADE_ENUMSET_OPERATORS(GlfwApplication::GLConfiguration::Flags) CORRADE_ENUMSET_OPERATORS(GlfwApplication::GLConfiguration::Flags)
#endif #endif
namespace Implementation {
enum class GlfwDpiScalingPolicy: UnsignedByte {
/* Using 0 for an "unset" value */
#ifdef CORRADE_TARGET_APPLE
Framebuffer = 1,
#endif
#ifndef CORRADE_TARGET_APPLE
Virtual = 2,
Physical = 3,
#endif
Default
#ifdef CORRADE_TARGET_APPLE
= Framebuffer
#else
= Virtual
#endif
};
}
/** /**
@brief Configuration @brief Configuration
@ -746,6 +828,62 @@ class GlfwApplication::Configuration {
*/ */
typedef Containers::EnumSet<WindowFlag> WindowFlags; typedef Containers::EnumSet<WindowFlag> WindowFlags;
/**
* @brief DPI scaling policy
*
* DPI scaling policy when requesting a particular window size. Can
* be overriden on command-line using `--magnum-dpi-scaling` or via
* the `MAGNUM_DPI_SCALING` environment variable.
* @see @ref setSize(), @ref Platform-Sdl2Application-dpi
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
enum class DpiScalingPolicy: UnsignedByte {
/**
* Framebuffer DPI scaling. The window will have the same size as
* requested, but the framebuffer size will be different. Supported
* only on macOS and iOS and is also the only supported value
* there.
*/
Framebuffer,
/**
* Virtual DPI scaling. Scales the window based on UI scaling
* setting in the system. Falls back to
* @ref DpiScalingPolicy::Physical on platforms that don't support
* it. Supported only on desktop platforms (except macOS) and it's
* the default there.
*
* Equivalent to `--magnum-dpi-scaling virtual` passed on
* command-line.
*/
Virtual,
/**
* Physical DPI scaling. Takes the requested window size as a
* physical size that a window would have on platform's default DPI
* and scales it to have the same size on given display physical
* DPI. On platforms that don't have a concept of a window it
* causes the framebuffer to match screen pixels 1:1 without any
* scaling. Supported on desktop platforms except macOS and on
* mobile and web. Default on mobile and web.
*
* Equivalent to `--magnum-dpi-scaling physical` passed on
* command-line.
*/
Physical,
/**
* Default policy for current platform. Alias to one of
* @ref DpiScalingPolicy::Framebuffer, @ref DpiScalingPolicy::Virtual
* or @ref DpiScalingPolicy::Physical depending on platform. See
* @ref Platform-Sdl2Application-dpi for details.
*/
Default
};
#else
typedef Implementation::GlfwDpiScalingPolicy DpiScalingPolicy;
#endif
/** @brief Cursor mode */ /** @brief Cursor mode */
enum class CursorMode: Int { enum class CursorMode: Int {
/** Visible unconstrained cursor */ /** Visible unconstrained cursor */
@ -778,14 +916,56 @@ class GlfwApplication::Configuration {
/** @brief Window size */ /** @brief Window size */
Vector2i size() const { return _size; } Vector2i size() const { return _size; }
/**
* @brief DPI scaling policy
*
* If @ref dpiScaling() is non-zero, it has a priority over this value.
* The `--magnum-dpi-scaling` command-line option has a priority over
* any application-set value.
* @see @ref setSize(const Vector2i&, DpiScalingPolicy)
*/
DpiScalingPolicy dpiScalingPolicy() const { return _dpiScalingPolicy; }
/**
* @brief Custom DPI scaling
*
* If zero, then @ref dpiScalingPolicy() has a priority over this
* value. The `--magnum-dpi-scaling` command-line option has a priority
* over any application-set value.
* @see @ref setSize(const Vector2i&, const Vector2&)
*/
Vector2 dpiScaling() const { return _dpiScaling; }
/** /**
* @brief Set window size * @brief Set window size
* @param size Desired window size
* @param dpiScalingPolicy Policy based on which DPI scaling will be set
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Default is @cpp {800, 600} @ce. * Default is @cpp {800, 600} @ce. See @ref Platform-GlfwApplication-dpi
* for more information.
* @see @ref setSize(const Vector2i&, const Vector2&)
*/
Configuration& setSize(const Vector2i& size, DpiScalingPolicy dpiScalingPolicy = DpiScalingPolicy::Default) {
_size = size;
_dpiScalingPolicy = dpiScalingPolicy;
return *this;
}
/**
* @brief Set window size with custom DPI scaling
* @param size Desired window size
* @param dpiScaling Custom DPI scaling value
*
* Compared to @ref setSize(const Vector2i&, DpiScalingPolicy) which
* autodetects the DPI scaling value according to given policy, this
* function sets the DPI scaling directly. The resulting
* @ref GlfwApplication::windowSize() is @cpp size*dpiScaling @ce and
* @ref GlfwApplication::dpiScaling() is @p dpiScaling.
*/ */
Configuration& setSize(const Vector2i& size) { Configuration& setSize(const Vector2i& size, const Vector2& dpiScaling) {
_size = size; _size = size;
_dpiScaling = dpiScaling;
return *this; return *this;
} }
@ -881,6 +1061,8 @@ class GlfwApplication::Configuration {
std::string _title; std::string _title;
Vector2i _size; Vector2i _size;
WindowFlags _windowFlags; WindowFlags _windowFlags;
DpiScalingPolicy _dpiScalingPolicy;
Vector2 _dpiScaling;
CursorMode _cursorMode; CursorMode _cursorMode;
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
Int _sampleCount; Int _sampleCount;

16
src/Magnum/Platform/Sdl2Application.cpp

@ -99,18 +99,18 @@ Sdl2Application::Sdl2Application(const Arguments& arguments, NoCreateT):
if(args.value("log") == "verbose") _verboseLog = true; if(args.value("log") == "verbose") _verboseLog = true;
const std::string dpiScaling = args.value("dpi-scaling"); const std::string dpiScaling = args.value("dpi-scaling");
if(dpiScaling == "default") if(dpiScaling == "default")
_commandLineDpiScalingPolicy = Implementation::DpiScalingPolicy::Default; _commandLineDpiScalingPolicy = Implementation::Sdl2DpiScalingPolicy::Default;
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
else if(dpiScaling == "framebuffer") else if(dpiScaling == "framebuffer")
_commandLineDpiScalingPolicy = Implementation::DpiScalingPolicy::Framebuffer; _commandLineDpiScalingPolicy = Implementation::Sdl2DpiScalingPolicy::Framebuffer;
#endif #endif
#ifndef CORRADE_TARGET_APPLE #ifndef CORRADE_TARGET_APPLE
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_ANDROID) #if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_ANDROID)
else if(dpiScaling == "virtual") else if(dpiScaling == "virtual")
_commandLineDpiScalingPolicy = Implementation::DpiScalingPolicy::Virtual; _commandLineDpiScalingPolicy = Implementation::Sdl2DpiScalingPolicy::Virtual;
#endif #endif
else if(dpiScaling == "physical") else if(dpiScaling == "physical")
_commandLineDpiScalingPolicy = Implementation::DpiScalingPolicy::Physical; _commandLineDpiScalingPolicy = Implementation::Sdl2DpiScalingPolicy::Physical;
#endif #endif
else if(dpiScaling.find_first_of(" \t\n") != std::string::npos) else if(dpiScaling.find_first_of(" \t\n") != std::string::npos)
_commandLineDpiScaling = args.value<Vector2>("dpi-scaling"); _commandLineDpiScaling = args.value<Vector2>("dpi-scaling");
@ -146,7 +146,7 @@ Vector2 Sdl2Application::dpiScaling(const Configuration& configuration) const {
/* Use values from the configuration only if not overriden on command line. /* Use values from the configuration only if not overriden on command line.
In any case explicit scaling has a precedence before the policy. */ In any case explicit scaling has a precedence before the policy. */
Implementation::DpiScalingPolicy dpiScalingPolicy{}; Implementation::Sdl2DpiScalingPolicy dpiScalingPolicy{};
if(!_commandLineDpiScaling.isZero()) { if(!_commandLineDpiScaling.isZero()) {
Debug{verbose} << "Platform::Sdl2Application: user-defined DPI scaling" << _commandLineDpiScaling.x(); Debug{verbose} << "Platform::Sdl2Application: user-defined DPI scaling" << _commandLineDpiScaling.x();
return _commandLineDpiScaling; return _commandLineDpiScaling;
@ -169,7 +169,7 @@ Vector2 Sdl2Application::dpiScaling(const Configuration& configuration) const {
#else #else
/* Try to get virtual DPI scaling first, if supported and requested */ /* Try to get virtual DPI scaling first, if supported and requested */
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_ANDROID) #if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_ANDROID)
if(dpiScalingPolicy == Implementation::DpiScalingPolicy::Virtual) { if(dpiScalingPolicy == Implementation::Sdl2DpiScalingPolicy::Virtual) {
/* Use Xft.dpi on X11 */ /* Use Xft.dpi on X11 */
#ifdef _MAGNUM_PLATFORM_USE_X11 #ifdef _MAGNUM_PLATFORM_USE_X11
const Vector2 dpiScaling{Implementation::x11DpiScaling()}; const Vector2 dpiScaling{Implementation::x11DpiScaling()};
@ -189,9 +189,9 @@ Vector2 Sdl2Application::dpiScaling(const Configuration& configuration) const {
/* At this point, either the virtual DPI query failed or a physical DPI /* At this point, either the virtual DPI query failed or a physical DPI
scaling is requested */ scaling is requested */
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_ANDROID) #if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_ANDROID)
CORRADE_INTERNAL_ASSERT(dpiScalingPolicy == Implementation::DpiScalingPolicy::Virtual || dpiScalingPolicy == Implementation::DpiScalingPolicy::Physical); CORRADE_INTERNAL_ASSERT(dpiScalingPolicy == Implementation::Sdl2DpiScalingPolicy::Virtual || dpiScalingPolicy == Implementation::Sdl2DpiScalingPolicy::Physical);
#else #else
CORRADE_INTERNAL_ASSERT(dpiScalingPolicy == Implementation::DpiScalingPolicy::Physical); CORRADE_INTERNAL_ASSERT(dpiScalingPolicy == Implementation::Sdl2DpiScalingPolicy::Physical);
#endif #endif
/* Take device pixel ratio on Emscripten */ /* Take device pixel ratio on Emscripten */

8
src/Magnum/Platform/Sdl2Application.h

@ -57,7 +57,7 @@
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
namespace Implementation { namespace Implementation {
enum class DpiScalingPolicy: UnsignedByte; enum class Sdl2DpiScalingPolicy: UnsignedByte;
} }
/** @nosubgrouping /** @nosubgrouping
@ -921,7 +921,7 @@ class Sdl2Application {
/* These are saved from command-line arguments */ /* These are saved from command-line arguments */
bool _verboseLog{}; bool _verboseLog{};
Implementation::DpiScalingPolicy _commandLineDpiScalingPolicy{}; Implementation::Sdl2DpiScalingPolicy _commandLineDpiScalingPolicy{};
Vector2 _commandLineDpiScaling; Vector2 _commandLineDpiScaling;
Vector2 _dpiScaling; Vector2 _dpiScaling;
@ -1139,7 +1139,7 @@ CORRADE_ENUMSET_OPERATORS(Sdl2Application::GLConfiguration::Flags)
#endif #endif
namespace Implementation { namespace Implementation {
enum class DpiScalingPolicy: UnsignedByte { enum class Sdl2DpiScalingPolicy: UnsignedByte {
/* Using 0 for an "unset" value */ /* Using 0 for an "unset" value */
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
@ -1339,7 +1339,7 @@ class Sdl2Application::Configuration {
Default Default
}; };
#else #else
typedef Implementation::DpiScalingPolicy DpiScalingPolicy; typedef Implementation::Sdl2DpiScalingPolicy DpiScalingPolicy;
#endif #endif
/*implicit*/ Configuration(); /*implicit*/ Configuration();

Loading…
Cancel
Save