diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 2f7f19ba5..d5ff2811f 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -584,13 +584,27 @@ void GlfwApplication::setupCallbacks() { #ifdef MAGNUM_TARGET_GL glfwSetFramebufferSizeCallback(_window, [](GLFWwindow* const window, const int w, const int h) { auto& app = *static_cast(glfwGetWindowUserPointer(window)); - ViewportEvent e{app.windowSize(), {w, h}, app.dpiScaling()}; + ViewportEvent e{ViewportEvent::Type::Resized, app.windowSize(), {w, h}, app.dpiScaling()}; app.viewportEvent(e); }); #else glfwSetWindowSizeCallback(_window, [](GLFWwindow* const window, const int w, const int h) { auto& app = *static_cast(glfwGetWindowUserPointer(window)); - ViewportEvent e{{w, h}, app.dpiScaling()}; + ViewportEvent e{ViewportEvent::Type::Resized, {w, h}, app.dpiScaling()}; + app.viewportEvent(e); + }); + #endif + #if GLFW_VERSION_MAJOR*100 + GLFW_VERSION_MINOR >= 303 + glfwSetWindowContentScaleCallback(_window, [](GLFWwindow* const window, float xScale, float yScale) { + auto& app = *static_cast(glfwGetWindowUserPointer(window)); + ViewportEvent e{ViewportEvent::Type::DpiScalingChanged, + #ifdef MAGNUM_TARGET_GL + app.windowSize(), app.framebufferSize(), + #else + app.windowSize(), + #endif + /* Update the cached DPI scaling value as well */ + app._dpiScaling = {xScale, yScale}}; app.viewportEvent(e); }); #endif diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index f62853ac6..f7f8410a5 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -1300,6 +1300,11 @@ class GlfwApplication::ExitEvent { */ class GlfwApplication::ViewportEvent { public: + enum class Type: UnsignedByte { + Resized, + DpiScalingChanged + }; + /** @brief Copying is not allowed */ ViewportEvent(const ViewportEvent&) = delete; @@ -1312,6 +1317,9 @@ class GlfwApplication::ViewportEvent { /** @brief Moving is not allowed */ ViewportEvent& operator=(ViewportEvent&&) = delete; + /** @brief Event type */ + Type type() const { return _type; } + /** * @brief Window size * @@ -1353,16 +1361,17 @@ class GlfwApplication::ViewportEvent { private: friend GlfwApplication; - explicit ViewportEvent(const Vector2i& windowSize, + explicit ViewportEvent(Type type, const Vector2i& windowSize, #ifdef MAGNUM_TARGET_GL const Vector2i& framebufferSize, #endif - const Vector2& dpiScaling): _windowSize{windowSize}, + const Vector2& dpiScaling): _type{type}, _windowSize{windowSize}, #ifdef MAGNUM_TARGET_GL _framebufferSize{framebufferSize}, #endif _dpiScaling{dpiScaling} {} + Type _type; const Vector2i _windowSize; #ifdef MAGNUM_TARGET_GL const Vector2i _framebufferSize; diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 276c7ee55..1d15d861e 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -65,6 +65,8 @@ #define WIN32_LEAN_AND_MEAN #endif #include +/* For capturing the WM_DPICHANGED event */ +#include #endif namespace Magnum { namespace Platform { @@ -155,6 +157,11 @@ Sdl2Application::Sdl2Application(const Arguments& arguments, NoCreateT): std::exit(1); } + #ifdef CORRADE_TARGET_WINDOWS + /* Enable SysWM events to get the WM_DPICHANGED event on Windows */ + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); + #endif + /* Save command-line arguments */ if(args.value("log") == "verbose") _verboseLog = true; const std::string dpiScaling = args.value("dpi-scaling"); @@ -834,7 +841,8 @@ bool Sdl2Application::mainLoopIteration() { _lastKnownCanvasSize = canvasSizei; const Vector2i size = _dpiScaling*canvasSizei; emscripten_set_canvas_element_size("#canvas", size.x(), size.y()); - ViewportEvent e{ + /** @todo dpi scaling changed? */ + ViewportEvent e{ViewportEvent::Type::Resized, #ifdef MAGNUM_TARGET_GL size, #endif @@ -864,7 +872,7 @@ bool Sdl2Application::mainLoopIteration() { framebuffer size and not window size on macOS, which is weird. Query the values directly instead to be really sure. */ - ViewportEvent e{event, windowSize(), + ViewportEvent e{ViewportEvent::Type::Resized, event, windowSize(), #ifdef MAGNUM_TARGET_GL framebufferSize(), #endif @@ -942,6 +950,21 @@ bool Sdl2Application::mainLoopIteration() { } } break; + #ifdef CORRADE_TARGET_WINDOWS + case SDL_SYSWMEVENT: { + if(event.syswm.msg->msg.win.msg == WM_DPICHANGED) { + DWORD dpi = event.syswm.msg->msg.win.wParam; + ViewportEvent e{ViewportEvent::Type::DpiScalingChanged, event, windowSize(), + #ifdef MAGNUM_TARGET_GL + framebufferSize(), + #endif + /* Update the cached DPI scaling value as well */ + _dpiScaling = Vector2{Vector2i{LOWORD(dpi), HIWORD(dpi)}}/96.0f}; + viewportEvent(e); + } + } break; + #endif + /* Direct everything else to anyEvent(), so users can implement event handling for things not present in the Application APIs */ default: if(!(_flags & Flag::NoAnyEvent)) anyEvent(event); diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index b2426d513..8d0fdfefa 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -1829,6 +1829,11 @@ class Sdl2Application::ExitEvent { */ class Sdl2Application::ViewportEvent { public: + enum class Type: UnsignedByte { + Resized, + DpiScalingChanged + }; + /** @brief Copying is not allowed */ ViewportEvent(const ViewportEvent&) = delete; @@ -1841,6 +1846,9 @@ class Sdl2Application::ViewportEvent { /** @brief Moving is not allowed */ ViewportEvent& operator=(ViewportEvent&&) = delete; + /** @brief Event type */ + Type type() const { return _type; } + /** * @brief Window size * @@ -1893,7 +1901,7 @@ class Sdl2Application::ViewportEvent { private: friend Sdl2Application; - explicit ViewportEvent( + explicit ViewportEvent(Type type, #ifndef CORRADE_TARGET_EMSCRIPTEN const SDL_Event& event, #endif @@ -1901,7 +1909,7 @@ class Sdl2Application::ViewportEvent { #ifdef MAGNUM_TARGET_GL const Vector2i& framebufferSize, #endif - const Vector2& dpiScaling): + const Vector2& dpiScaling): _type{type}, #ifndef CORRADE_TARGET_EMSCRIPTEN _event(event), #endif @@ -1911,6 +1919,7 @@ class Sdl2Application::ViewportEvent { #endif _dpiScaling{dpiScaling} {} + Type _type; #ifndef CORRADE_TARGET_EMSCRIPTEN const SDL_Event& _event; #endif diff --git a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp index df4a65dd3..6faa792bf 100644 --- a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp +++ b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp @@ -47,6 +47,11 @@ struct GlfwApplicationTest: Platform::Application { << event.framebufferSize() #endif << event.dpiScaling(); + + if(event.type() == ViewportEvent::Type::DpiScalingChanged) { + Debug{} << "DPI scaling changed, resizing to" << _lastUnscaledWindowSize; + setWindowSize(_lastUnscaledWindowSize); + } else _lastUnscaledWindowSize = event.windowSize()/event.dpiScaling(); } void keyPressEvent(KeyEvent& event) override { @@ -96,6 +101,9 @@ struct GlfwApplicationTest: Platform::Application { } void drawEvent() override {} + + private: + Vector2i _lastUnscaledWindowSize; }; GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform::Application{arguments, NoCreate} { @@ -116,6 +124,10 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform:: #endif << dpiScaling(); + /* Save desired window size for resizing when going between differently + dense displays */ + _lastUnscaledWindowSize = windowSize()/dpiScaling(); + #if GLFW_VERSION_MAJOR*100 + GLFW_VERSION_MINOR >= 302 Utility::Resource rs{"icons"}; PluginManager::Manager manager; diff --git a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp index a16ad9ddf..9275170ae 100644 --- a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp +++ b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp @@ -66,6 +66,11 @@ struct Sdl2ApplicationTest: Platform::Application { << event.framebufferSize() #endif << event.dpiScaling(); + + if(event.type() == ViewportEvent::Type::DpiScalingChanged) { + Debug{} << "DPI scaling changed, resizing to" << _lastUnscaledWindowSize; + setWindowSize(_lastUnscaledWindowSize); + } else _lastUnscaledWindowSize = event.windowSize()/event.dpiScaling(); } /* For testing event coordinates */ @@ -137,10 +142,12 @@ struct Sdl2ApplicationTest: Platform::Application { if(event.type == SDL_WINDOWEVENT) d << event.window.event; } - #ifdef CORRADE_TARGET_EMSCRIPTEN private: + #ifdef CORRADE_TARGET_EMSCRIPTEN bool _fullscreen = false; - #endif + #else + Vector2i _lastUnscaledWindowSize; + #endif }; Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform::Application{arguments, NoCreate} { @@ -162,6 +169,10 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform:: #endif << dpiScaling(); + /* Save desired window size for resizing when going between differently + dense displays */ + _lastUnscaledWindowSize = windowSize()/dpiScaling(); + #ifndef CORRADE_TARGET_EMSCRIPTEN #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2005 Utility::Resource rs{"icons"};