diff --git a/doc/changelog.dox b/doc/changelog.dox index 0618753af..564698968 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -173,6 +173,9 @@ See also: @subsubsection changelog-latest-changes-platform Platform libraries +- @ref Platform::Sdl2Application::viewportEvent() "Platform::*Application::viewportEvent()" + now gets all information needed for DPI-aware rendering instead of just + a framebuffer size --- now also window size and the DPI scaling value - @ref Platform::GlfwApplication now behaves the same as @ref Platform::Sdl2Application when creating an OpenGL context: first it attempts to create a forward-compatible core OpenGL 3.2+ context and if @@ -183,6 +186,9 @@ See also: pointer - @ref Platform::GlfwApplication now loads modifiers for mouse move and mouse scroll events lazily, only when needed +- @ref Platform::BasicScreen::viewportEvent() "Platform::Screen::viewportEvent()" + is no longer pure virtual to be consistent with all `*Application` + implementations @subsubsection changelog-latest-changes-shaders Shaders library @@ -271,6 +277,10 @@ See also: scheduled for removal in a future release. Please consider switching to @ref Platform::Sdl2Application or @ref Platform::GlfwApplication as soon as possible. +- `Platform::*Application::viewportEvent(const Vector2i&)` is deprecated + because it doesn't provide all information needed for DPI-aware rendering. + Override the @ref Platform::Sdl2Application::viewportEvent(ViewportEvent&) "viewportEvent(ViewportEvent&)" + function instead. - `Math::Geometry`, `Math::Geometry::Distance` and `Math::Geometry::Intersection` namespaces are deprecated for being too deeply nested, use @ref Math::Distance and @ref Math::Intersection instead diff --git a/doc/snippets/MagnumGL-framebuffer.cpp b/doc/snippets/MagnumGL-framebuffer.cpp index 53bf8ec90..7f1267284 100644 --- a/doc/snippets/MagnumGL-framebuffer.cpp +++ b/doc/snippets/MagnumGL-framebuffer.cpp @@ -31,8 +31,8 @@ using namespace Magnum; struct A: Platform::Sdl2Application { /* [DefaultFramebuffer-usage-viewport] */ -void viewportEvent(const Vector2i& size) override { - GL::defaultFramebuffer.setViewport({{}, size}); +void viewportEvent(ViewportEvent& event) override { + GL::defaultFramebuffer.setViewport({{}, event.framebufferSize()}); // ... } diff --git a/doc/snippets/MagnumPlatform-portability.cpp b/doc/snippets/MagnumPlatform-portability.cpp index 971d50bfb..108e3d76c 100644 --- a/doc/snippets/MagnumPlatform-portability.cpp +++ b/doc/snippets/MagnumPlatform-portability.cpp @@ -38,7 +38,7 @@ class MyApplication: public Platform::Application { MyApplication(const Arguments& arguments); protected: - void viewportEvent(const Vector2i& size) override; + void viewportEvent(ViewportEvent& size) override; void drawEvent() override; void keyPressEvent(KeyEvent& event) override; }; diff --git a/doc/snippets/MagnumPlatform.cpp b/doc/snippets/MagnumPlatform.cpp index 5a6cdf618..c3f7ce440 100644 --- a/doc/snippets/MagnumPlatform.cpp +++ b/doc/snippets/MagnumPlatform.cpp @@ -65,13 +65,13 @@ class MyApplication: public Platform::Application { // ... private: - void viewportEvent(const Vector2i& size) override; + void viewportEvent(ViewportEvent& event) override; }; // ... -void MyApplication::viewportEvent(const Vector2i& size) { - GL::defaultFramebuffer.setViewport({{}, size}); +void MyApplication::viewportEvent(ViewportEvent& event) { + GL::defaultFramebuffer.setViewport({{}, event.framebufferSize()}); } /* [size] */ diff --git a/src/Magnum/Platform/AbstractXApplication.cpp b/src/Magnum/Platform/AbstractXApplication.cpp index 3b458d5e8..1ab74b5b8 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -156,7 +156,8 @@ int AbstractXApplication::exec() { Vector2i size(event.xconfigure.width, event.xconfigure.height); if(size != _windowSize) { _windowSize = size; - viewportEvent(size); + ViewportEvent e{size}; + viewportEvent(e); _flags |= Flag::Redraw; } } break; @@ -190,7 +191,20 @@ int AbstractXApplication::exec() { return 0; } +void AbstractXApplication::viewportEvent(ViewportEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + viewportEvent(event.framebufferSize()); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED void AbstractXApplication::viewportEvent(const Vector2i&) {} +#endif + void AbstractXApplication::keyPressEvent(KeyEvent&) {} void AbstractXApplication::keyReleaseEvent(KeyEvent&) {} void AbstractXApplication::mousePressEvent(MouseEvent&) {} diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index 284ef6d5f..755cf7dbd 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -73,6 +73,7 @@ class AbstractXApplication { class Configuration; class GLConfiguration; + class ViewportEvent; class InputEvent; class KeyEvent; class MouseEvent; @@ -211,8 +212,13 @@ class AbstractXApplication { #else private: #endif - /** @copydoc Sdl2Application::viewportEvent() */ - virtual void viewportEvent(const Vector2i& size); + /** @copydoc GlfwApplication::viewportEvent(ViewportEvent&) */ + virtual void viewportEvent(ViewportEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** @copydoc GlfwApplication::viewportEvent(const Vector2i&) */ + virtual CORRADE_DEPRECATED("use viewportEvent(ViewportEvent&) instead") void viewportEvent(const Vector2i& size); + #endif /** @copydoc Sdl2Application::drawEvent() */ virtual void drawEvent() = 0; @@ -363,6 +369,37 @@ class AbstractXApplication::Configuration { #endif }; +/** +@brief Viewport event + +@see @ref viewportEvent() +*/ +class AbstractXApplication::ViewportEvent { + public: + /** + * @brief Window size + * + * Same as @ref framebufferSize(). + * @see @ref AbstractXApplication::windowSize() + */ + Vector2i windowSize() const { return _size; } + + /** + * @brief Framebuffer size + * + * Same as @ref windowSize(). + * @see @ref AbstractXApplication::framebufferSize() + */ + Vector2i framebufferSize() const { return _size; } + + private: + friend AbstractXApplication; + + explicit ViewportEvent(const Vector2i& size): _size{size} {} + + Vector2i _size; +}; + /** @brief Base for input events diff --git a/src/Magnum/Platform/AndroidApplication.cpp b/src/Magnum/Platform/AndroidApplication.cpp index 48df834a7..448859708 100644 --- a/src/Magnum/Platform/AndroidApplication.cpp +++ b/src/Magnum/Platform/AndroidApplication.cpp @@ -174,7 +174,20 @@ void AndroidApplication::swapBuffers() { eglSwapBuffers(_display, _surface); } +void AndroidApplication::viewportEvent(ViewportEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + viewportEvent(event.windowSize()); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED void AndroidApplication::viewportEvent(const Vector2i&) {} +#endif + void AndroidApplication::mousePressEvent(MouseEvent&) {} void AndroidApplication::mouseReleaseEvent(MouseEvent&) {} void AndroidApplication::mouseMoveEvent(MouseMoveEvent&) {} diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index ceea514e1..e99e09fa2 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -143,6 +143,7 @@ class AndroidApplication { class Configuration; class GLConfiguration; + class ViewportEvent; class InputEvent; class MouseEvent; class MouseMoveEvent; @@ -324,8 +325,13 @@ class AndroidApplication { #else private: #endif - /** @copydoc Sdl2Application::viewportEvent() */ - virtual void viewportEvent(const Vector2i& size); + /** @copydoc GlfwApplication::viewportEvent(ViewportEvent&) */ + virtual void viewportEvent(ViewportEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** @copydoc GlfwApplication::viewportEvent(const Vector2i&) */ + virtual CORRADE_DEPRECATED("use viewportEvent(ViewportEvent&) instead") void viewportEvent(const Vector2i& size); + #endif /** @copydoc Sdl2Application::drawEvent() */ virtual void drawEvent() = 0; @@ -506,6 +512,28 @@ class AndroidApplication::Configuration { Vector2i _size; }; +/** +@brief Viewport event + +@see @ref viewportEvent() +*/ +class AndroidApplication::ViewportEvent { + public: + /** + * @brief Window size + * + * @see @ref AndroidApplication::windowSize() + */ + Vector2i windowSize() const { return _windowSize; } + + private: + friend AndroidApplication; + + explicit ViewportEvent(const Vector2i& windowSize): _windowSize{windowSize} {} + + Vector2i _windowSize; +}; + /** @brief Base for input events diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 0fa165605..f3b33d5a6 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -355,7 +355,8 @@ void GlfwApplication::setupCallbacks() { static_cast(glfwGetWindowUserPointer(window))->drawEvent(); }); glfwSetFramebufferSizeCallback(_window, [](GLFWwindow* const window, const int w, const int h) { - static_cast(glfwGetWindowUserPointer(window))->viewportEvent({w, h}); + ViewportEvent e{{w, h}}; + static_cast(glfwGetWindowUserPointer(window))->viewportEvent(e); }); glfwSetKeyCallback(_window, [](GLFWwindow* const window, const int key, int, const int action, const int mods) { const auto instance = static_cast(glfwGetWindowUserPointer(window)); @@ -469,7 +470,20 @@ auto GlfwApplication::MouseScrollEvent::modifiers() -> Modifiers { return *_modifiers; } +void GlfwApplication::viewportEvent(ViewportEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + viewportEvent(event.windowSize()); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED void GlfwApplication::viewportEvent(const Vector2i&) {} +#endif + void GlfwApplication::keyPressEvent(KeyEvent&) {} void GlfwApplication::keyReleaseEvent(KeyEvent&) {} void GlfwApplication::mousePressEvent(MouseEvent&) {} diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 7e89a871a..10231969e 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -130,6 +130,7 @@ class GlfwApplication { #ifdef MAGNUM_TARGET_GL class GLConfiguration; #endif + class ViewportEvent; class InputEvent; class KeyEvent; class MouseEvent; @@ -365,8 +366,37 @@ class GlfwApplication { #else private: #endif - /** @copydoc Sdl2Application::viewportEvent() */ - virtual void viewportEvent(const Vector2i& size); + /** + * @brief Viewport event + * + * Called when window size changes. The default implementation does + * nothing. If you want to respond to size changes, you should pass the + * new size to @ref GL::DefaultFramebuffer::setViewport() (if using + * OpenGL) and possibly elsewhere (to + * @ref SceneGraph::Camera::setViewport(), other framebuffers...). + * + * Note that this function might not get called at all if the window + * size doesn't change. You should configure the initial state of your + * cameras, framebuffers etc. in application constructor rather than + * relying on this function to be called. Size of the window can be + * retrieved also using @ref windowSize(). + * + * @todoc make this a copydoc of Sdl2Application once both have + * framebufferSize() and dpiScaling() + */ + virtual void viewportEvent(ViewportEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief viewportEvent(ViewportEvent&) + * @deprecated Use @ref viewportEvent(ViewportEvent&) instead. + * To preserve backwards compatibility, this function is called + * from @ref viewportEvent(ViewportEvent&) with + * @ref ViewportEvent::windowSize() passed to @p size. Overriding + * the new function will cause this function to not be called + * anymore. + */ + virtual CORRADE_DEPRECATED("use viewportEvent(ViewportEvent&) instead") void viewportEvent(const Vector2i& size); + #endif /** @copydoc Sdl2Application::drawEvent() */ virtual void drawEvent() = 0; @@ -862,6 +892,28 @@ class GlfwApplication::Configuration { CORRADE_ENUMSET_OPERATORS(GlfwApplication::Configuration::WindowFlags) +/** +@brief Viewport event + +@see @ref viewportEvent() +*/ +class GlfwApplication::ViewportEvent { + public: + /** + * @brief Window size + * + * @see @ref GlfwApplication::windowSize() + */ + Vector2i windowSize() const { return _windowSize; } + + private: + friend GlfwApplication; + + explicit ViewportEvent(const Vector2i& windowSize): _windowSize{windowSize} {} + + Vector2i _windowSize; +}; + /** @brief Base for input events diff --git a/src/Magnum/Platform/GlutApplication.cpp b/src/Magnum/Platform/GlutApplication.cpp index abc3304ba..cb11c27d9 100644 --- a/src/Magnum/Platform/GlutApplication.cpp +++ b/src/Magnum/Platform/GlutApplication.cpp @@ -134,6 +134,11 @@ bool GlutApplication::tryCreate(const Configuration& configuration, const GLConf GlutApplication::~GlutApplication() = default; +void GlutApplication::staticViewportEvent(int x, int y) { + ViewportEvent e{{x, y}}; + _instance->viewportEvent(e); +} + void GlutApplication::staticKeyPressEvent(unsigned char key, int x, int y) { KeyEvent e(static_cast(key), {x, y}); _instance->keyPressEvent(e); @@ -167,7 +172,20 @@ void GlutApplication::staticMouseMoveEvent(int x, int y) { _instance->mouseMoveEvent(e); } +void GlutApplication::viewportEvent(ViewportEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + viewportEvent(event.windowSize()); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED void GlutApplication::viewportEvent(const Vector2i&) {} +#endif + void GlutApplication::keyPressEvent(KeyEvent&) {} void GlutApplication::keyReleaseEvent(KeyEvent&) {} void GlutApplication::mousePressEvent(MouseEvent&) {} diff --git a/src/Magnum/Platform/GlutApplication.h b/src/Magnum/Platform/GlutApplication.h index 6441a6c10..ff65dcced 100644 --- a/src/Magnum/Platform/GlutApplication.h +++ b/src/Magnum/Platform/GlutApplication.h @@ -134,6 +134,7 @@ class CORRADE_DEPRECATED("Scheduled for removal. Consider switching to Sdl2Appli class Configuration; class GLConfiguration; + class ViewportEvent; class InputEvent; class KeyEvent; class MouseEvent; @@ -300,8 +301,33 @@ class CORRADE_DEPRECATED("Scheduled for removal. Consider switching to Sdl2Appli #else private: #endif - /** @copydoc Sdl2Application::viewportEvent() */ - virtual void viewportEvent(const Vector2i& size); + /** + * @brief Viewport event + * + * Called when window size changes. The default implementation does + * nothing. If you want to respond to size changes, you should pass the + * new size to @ref GL::DefaultFramebuffer::setViewport() (if using + * OpenGL) and possibly elsewhere (to + * @ref SceneGraph::Camera::setViewport(), other framebuffers...). + * + * Note that this function might not get called at all if the window + * size doesn't change. You should configure the initial state of your + * cameras, framebuffers etc. in application constructor rather than + * relying on this function to be called. + */ + virtual void viewportEvent(ViewportEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief viewportEvent(ViewportEvent&) + * @deprecated Use @ref viewportEvent(ViewportEvent&) instead. + * To preserve backwards compatibility, this function is called + * from @ref viewportEvent(ViewportEvent&) with + * @ref ViewportEvent::windowSize() passed to @p size. Overriding + * the new function will cause this function to not be called + * anymore. + */ + virtual CORRADE_DEPRECATED("use viewportEvent(ViewportEvent&) instead") void viewportEvent(const Vector2i& size); + #endif /** @copydoc Sdl2Application::drawEvent() */ virtual void drawEvent() = 0; @@ -374,9 +400,7 @@ class CORRADE_DEPRECATED("Scheduled for removal. Consider switching to Sdl2Appli /*@}*/ private: - static void staticViewportEvent(int x, int y) { - _instance->viewportEvent({x, y}); - } + static void staticViewportEvent(int x, int y); static void staticKeyPressEvent(unsigned char key, int x, int y); static void staticKeyReleaseEvent(unsigned char key, int x, int y); @@ -587,6 +611,24 @@ class GlutApplication::Configuration { #endif }; +/** +@brief Viewport event + +@see @ref viewportEvent() +*/ +class GlutApplication::ViewportEvent { + public: + /** @brief Window size */ + Vector2i windowSize() const { return _windowSize; } + + private: + friend GlutApplication; + + explicit ViewportEvent(const Vector2i& windowSize): _windowSize{windowSize} {} + + Vector2i _windowSize; +}; + /** @brief Base for input events diff --git a/src/Magnum/Platform/Screen.h b/src/Magnum/Platform/Screen.h index f1615ffa6..a879acd9d 100644 --- a/src/Magnum/Platform/Screen.h +++ b/src/Magnum/Platform/Screen.h @@ -102,6 +102,9 @@ template class BasicScreen: private Containers::LinkedListIte typedef Implementation::PropagatedScreenEvents PropagatedEvents; #endif + /** @brief Viewport event */ + typedef typename BasicScreenedApplication::ViewportEvent ViewportEvent; + /** @brief Input event */ typedef typename BasicScreenedApplication::InputEvent InputEvent; @@ -197,7 +200,19 @@ template class BasicScreen: private Containers::LinkedListIte * for more information. Setting viewport on default framebuffer should * be done by the holder application. */ - virtual void viewportEvent(const Vector2i& size) = 0; + virtual void viewportEvent(ViewportEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief viewportEvent(ViewportEvent&) + * @deprecated Use @ref viewportEvent(ViewportEvent&) instead. + * To preserve backwards compatibility, this function is called + * from @ref viewportEvent(ViewportEvent&) with + * @ref Sdl2Application::ViewportEvent::windowSize() "*Application::ViewportEvent::windowSize()" + * passed to @p size. Overriding the new function will cause this + * function to not be called anymore. + */ + virtual CORRADE_DEPRECATED("use viewportEvent(ViewportEvent&) instead") void viewportEvent(const Vector2i& size); + #endif /** * @brief Draw event diff --git a/src/Magnum/Platform/ScreenedApplication.h b/src/Magnum/Platform/ScreenedApplication.h index 551001bec..c9174bcf4 100644 --- a/src/Magnum/Platform/ScreenedApplication.h +++ b/src/Magnum/Platform/ScreenedApplication.h @@ -204,7 +204,7 @@ template class BasicScreenedApplication: public Application, * implementation does nothing. See @ref Sdl2Application::viewportEvent() "*Application::viewportEvent()" * for more information. */ - virtual void globalViewportEvent(const Vector2i& size); + virtual void globalViewportEvent(typename Application::ViewportEvent& size); /** * @brief Draw event @@ -222,11 +222,10 @@ template class BasicScreenedApplication: public Application, friend Containers::LinkedListItem, BasicScreenedApplication>; friend BasicScreen; #endif - /* The user is supposed to override only globalViewportEvent() and globalDrawEvent(), these implementations are dispatching the events to attached screens. */ - void viewportEvent(const Vector2i& size) override final; + void viewportEvent(typename Application::ViewportEvent& event) override final; void drawEvent() override final; void keyPressEvent(typename Application::KeyEvent& event) override final; void keyReleaseEvent(typename Application::KeyEvent& event) override final; diff --git a/src/Magnum/Platform/ScreenedApplication.hpp b/src/Magnum/Platform/ScreenedApplication.hpp index e1fb5c1b2..98d6b1435 100644 --- a/src/Magnum/Platform/ScreenedApplication.hpp +++ b/src/Magnum/Platform/ScreenedApplication.hpp @@ -37,6 +37,20 @@ namespace Magnum { namespace Platform { template BasicScreen::BasicScreen() = default; template BasicScreen::~BasicScreen() = default; +template void BasicScreen::viewportEvent(ViewportEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + viewportEvent(event.windowSize()); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED +template void BasicScreen::viewportEvent(const Vector2i&) {} +#endif + template void BasicScreen::keyPressEvent(KeyEvent&) {} template void BasicScreen::keyReleaseEvent(KeyEvent&) {} template void BasicScreen::mousePressEvent(MouseEvent&) {} @@ -78,13 +92,13 @@ template BasicScreenedApplication& BasicScreened return *this; } -template void BasicScreenedApplication::globalViewportEvent(const Vector2i&) {} +template void BasicScreenedApplication::globalViewportEvent(typename Application::ViewportEvent&) {} -template void BasicScreenedApplication::viewportEvent(const Vector2i& size) { +template void BasicScreenedApplication::viewportEvent(typename Application::ViewportEvent& event) { /* Call global event before all other (to resize framebuffer first) */ - globalViewportEvent(size); + globalViewportEvent(event); - for(BasicScreen& s: *this) s.viewportEvent(size); + for(BasicScreen& s: *this) s.viewportEvent(event); } template void BasicScreenedApplication::drawEvent() { diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index af7b37d22..52e6de855 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -573,15 +573,9 @@ void Sdl2Application::mainLoopIteration() { case SDL_WINDOWEVENT: switch(event.window.event) { case SDL_WINDOWEVENT_RESIZED: { - #ifndef CORRADE_TARGET_IOS - viewportEvent({event.window.data1, event.window.data2}); - #else - /* On iOS the window event is in points and not pixels, - but we need pixels to call glViewport() properly */ - Vector2i drawableSize; - SDL_GL_GetDrawableSize(_window, &drawableSize.x(), &drawableSize.y()); - viewportEvent(drawableSize); - #endif + ViewportEvent e{{event.window.data1, event.window.data2}, framebufferSize(), _dpiScaling}; + /** @todo handle also WM_DPICHANGED events when a window is moved between displays with different DPI */ + viewportEvent(e); _flags |= Flag::Redraw; } break; case SDL_WINDOWEVENT_EXPOSED: @@ -738,7 +732,20 @@ void Sdl2Application::tickEvent() { _flags |= Flag::NoTickEvent; } +void Sdl2Application::viewportEvent(ViewportEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + viewportEvent(event.framebufferSize()); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED void Sdl2Application::viewportEvent(const Vector2i&) {} +#endif + void Sdl2Application::keyPressEvent(KeyEvent&) {} void Sdl2Application::keyReleaseEvent(KeyEvent&) {} void Sdl2Application::mousePressEvent(MouseEvent&) {} diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index e9de03375..db1c55033 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -339,6 +339,7 @@ class Sdl2Application { #ifdef MAGNUM_TARGET_GL class GLConfiguration; #endif + class ViewportEvent; class InputEvent; class KeyEvent; class MouseEvent; @@ -682,17 +683,34 @@ class Sdl2Application { * * Called when window size changes. The default implementation does * nothing. If you want to respond to size changes, you should pass the - * new size to @ref GL::DefaultFramebuffer::setViewport() (if using - * OpenGL) and possibly elsewhere (to - * @ref SceneGraph::Camera::setViewport(), other framebuffers...). + * new *framebuffer* size to @ref GL::DefaultFramebuffer::setViewport() + * (if using OpenGL) and possibly elsewhere (to + * @ref SceneGraph::Camera::setViewport(), other framebuffers...) and + * the new *window* size and DPI scaling to APIs that respond to user + * events or scale UI elements. * * Note that this function might not get called at all if the window * size doesn't change. You should configure the initial state of your * cameras, framebuffers etc. in application constructor rather than - * relying on this function to be called. Viewport of default - * framebuffer can be retrieved via @ref GL::DefaultFramebuffer::viewport(). + * relying on this function to be called. Size of the window can be + * retrieved using @ref windowSize(), size of the backing framebuffer + * via @ref framebufferSize() and DPI scaling using @ref dpiScaling(). + * See @ref Platform-Sdl2Application-dpi for detailed info about these + * values. */ - virtual void viewportEvent(const Vector2i& size); + virtual void viewportEvent(ViewportEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief viewportEvent(ViewportEvent&) + * @deprecated Use @ref viewportEvent(ViewportEvent&) instead. + * To preserve backwards compatibility, this function is called + * from @ref viewportEvent(ViewportEvent&) with + * @ref ViewportEvent::framebufferSize() passed to @p size. + * Overriding the new function will cause this function to not be + * called anymore. + */ + virtual CORRADE_DEPRECATED("use viewportEvent(ViewportEvent&) instead") void viewportEvent(const Vector2i& size); + #endif /** * @brief Draw event @@ -1432,6 +1450,53 @@ class Sdl2Application::Configuration { #endif }; +/** +@brief Viewport event + +@see @ref viewportEvent() +*/ +class Sdl2Application::ViewportEvent { + public: + /** + * @brief Window size + * + * On some platforms with HiDPI displays, window size can be different + * from @ref framebufferSize(). See @ref Platform-Sdl2Application-dpi + * for more information. + * @see @ref Sdl2Application::windowSize() + */ + Vector2i windowSize() const { return _windowSize; } + + /** + * @brief Framebuffer size + * + * On some platforms with HiDPI displays, framebuffer size can be + * different from @ref windowSize(). See + * @ref Platform-Sdl2Application-dpi for more information. + * @see @ref Sdl2Application::framebufferSize() + */ + Vector2i framebufferSize() const { return _framebufferSize; } + + /** + * @brief DPI scaling + * + * On some platforms moving an app between displays can result in DPI + * scaling value being changed in tandem with a window/framebuffer + * size. Simply resizing a window doesn't change the DPI scaling value. + * See @ref Platform-Sdl2Application-dpi for more information. + * @see @ref Sdl2Application::dpiScaling() + */ + Vector2 dpiScaling() const { return _dpiScaling; } + + private: + friend Sdl2Application; + + explicit ViewportEvent(const Vector2i& windowSize, const Vector2i& framebufferSize, const Vector2& dpiScaling): _windowSize{windowSize}, _framebufferSize{framebufferSize}, _dpiScaling{dpiScaling} {} + + Vector2i _windowSize, _framebufferSize; + Vector2 _dpiScaling; +}; + /** @brief Base for input events