From 1e9d9cfd0fed85c8dee7087329559eaf58a5d89d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 13 Oct 2024 18:02:10 +0200 Subject: [PATCH] Platform: add proper mouseScrollEvent() to XApplication. And deprecate WheelDown and WheelUp. Funnily enough a similar change was done for *all other* applications including now-long-gone implementations like NaClApplication back in 2a77856df2e7d55ec587306f6184072865ba20b2, which was 2016!! Frankly, I was first thinking that I'd just deprecate this thing and not update it anymore, but it seems there's still a use case for a lightweight wrapper sitting right on top of system APIs. SDL / GLFW is too heavy for when one just needs to display stuff or debug GPU issues for which it isn't clear whether they're the driver's fault or the tookit's. And WindowlessApplication implementations proved very useful for this, so I guess a similar windowed application still makes sense, even if not very featureful. Additionally, for Vulkan I might take a stab at implementing a WaylandApplication if even just an attempt to understand how the swapchain works internally, and having an XApplication available would be handy to compare the behavior. --- doc/changelog.dox | 7 +- src/Magnum/Platform/AbstractXApplication.cpp | 27 +++++++- src/Magnum/Platform/AbstractXApplication.h | 69 +++++++++++++++++-- .../Test/AbstractXApplicationTest.cpp | 7 ++ 4 files changed, 103 insertions(+), 7 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index d953209f0..7b6a293c5 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -807,7 +807,8 @@ See also: UI scale. However note that this does not yet properly handle DPI change events themselves, which happen for example when moving windows across displays with different DPI. -- Added more keys to @ref Platform::AbstractXApplication::KeyEvent::Key for +- Added more keys to @ref Platform::AbstractXApplication::KeyEvent::Key and + implemented @ref Platform::AbstractXApplication::mouseScrollEvent() for better consistency with other application implementations @subsubsection changelog-latest-changes-scenegraph SceneGraph library @@ -1396,6 +1397,10 @@ See also: @relativeref{Platform::Sdl2Application,PointerMoveEvent} APIs that provide a better abstraction over general pointer input, not just a mouse alone. The same change is done in @ref Platform::GlfwApplication. +- @ref Platform::AbstractXApplication::MouseEvent::Button `WheelUp` and + `WheelDown` members are deprecated in favor of a dedicated + @ref Platform::AbstractXApplication::mouseScrollEvent(). Similar change was + done for all other application classes in 2016 already. - @cpp Shaders::DistanceFieldVector @ce, @cpp Shaders::Flat @ce, @cpp Shaders::Generic @ce, @cpp Shaders::MeshVisualizer2D @ce, @cpp Shaders::MeshVisualizer3D @ce, @cpp Shaders::Phong @ce, diff --git a/src/Magnum/Platform/AbstractXApplication.cpp b/src/Magnum/Platform/AbstractXApplication.cpp index 8d84f51c9..43e7e5f94 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -174,8 +174,19 @@ bool AbstractXApplication::mainLoopIteration() { } break; case ButtonPress: case ButtonRelease: { - MouseEvent e(static_cast(event.xbutton.button), event.xkey.state, {event.xbutton.x, event.xbutton.y}); - event.type == ButtonPress ? mousePressEvent(e) : mouseReleaseEvent(e); + /* Expose wheel as a scroll event, consistently with all other + applications */ + if(event.xbutton.button == 4 /*Button4*/ || + event.xbutton.button == 5 /*Button5*/) { + MouseScrollEvent e{Vector2::yAxis(event.xbutton.button == 4 ? 1.0f : -1.0f), {event.xbutton.x, event.xbutton.y}, event.xbutton.state}; + /* It reports both press and release. Fire the scroll event + just on press. */ + if(event.type == ButtonPress) + mouseScrollEvent(e); + } else { + MouseEvent e(MouseEvent::Button(event.xbutton.button), event.xkey.state, {event.xbutton.x, event.xbutton.y}); + event.type == ButtonPress ? mousePressEvent(e) : mouseReleaseEvent(e); + } } break; /* Mouse move events */ @@ -201,6 +212,18 @@ void AbstractXApplication::mousePressEvent(MouseEvent&) {} void AbstractXApplication::mouseReleaseEvent(MouseEvent&) {} void AbstractXApplication::mouseMoveEvent(MouseMoveEvent&) {} +void AbstractXApplication::mouseScrollEvent(MouseScrollEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + MouseEvent e{event.offset().y() > 0.0f ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, event._modifiers, event.position()}; + mousePressEvent(e); + mouseReleaseEvent(e); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + AbstractXApplication::GLConfiguration::GLConfiguration(): _version(GL::Version::None) {} AbstractXApplication::GLConfiguration::~GLConfiguration() = default; diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index 886f63da1..c9474efe7 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -106,6 +106,7 @@ class AbstractXApplication { class KeyEvent; class MouseEvent; class MouseMoveEvent; + class MouseScrollEvent; /** @brief Copying is not allowed */ AbstractXApplication(const AbstractXApplication&) = delete; @@ -296,6 +297,20 @@ class AbstractXApplication { /** @copydoc Sdl2Application::mouseMoveEvent() */ virtual void mouseMoveEvent(MouseMoveEvent& event); + /** + * @brief Mouse scroll event + * @m_since_latest + * + * Called when a scrolling device is used (mouse wheel or scrolling + * area on a touchpad). + * + * On builds with @ref MAGNUM_BUILD_DEPRECATED enabled, default + * implementation delegates to @ref mousePressEvent() and + * @ref mouseReleaseEvent() with @ref MouseEvent::Button::WheelDown and + * @ref MouseEvent::Button::WheelUp. + */ + virtual void mouseScrollEvent(MouseScrollEvent& event); + /* Since 1.8.17, the original short-hand group closing doesn't work anymore. FFS. */ /** @@ -660,6 +675,10 @@ class AbstractXApplication::InputEvent { #endif private: + #ifdef MAGNUM_BUILD_DEPRECATED + friend AbstractXApplication; /* mouseScrollEvent() backwards compat */ + #endif + unsigned int _modifiers; bool _accepted; }; @@ -1027,7 +1046,8 @@ class AbstractXApplication::KeyEvent: public AbstractXApplication::InputEvent { /** @brief Mouse event -@see @ref MouseMoveEvent, @ref mousePressEvent(), @ref mouseReleaseEvent() +@see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(), + @ref mouseReleaseEvent() */ class AbstractXApplication::MouseEvent: public AbstractXApplication::InputEvent { public: @@ -1040,8 +1060,22 @@ class AbstractXApplication::MouseEvent: public AbstractXApplication::InputEvent Left = 1 /*Button1*/, /**< Left button */ Middle = 2 /*Button2*/, /**< Middle button */ Right = 3 /*Button3*/, /**< Right button */ - WheelUp = 4 /*Button4*/, /**< Wheel up */ - WheelDown = 5 /*Button5*/ /**< Wheel down */ + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * Wheel up + * @m_deprecated_since_latest Implement @ref mouseScrollEvent() + * instead. + */ + WheelUp CORRADE_DEPRECATED_ENUM("implement mouseScrollEvent() instead") = 4, + + /** + * Wheel down + * @m_deprecated_since_latest Implement @ref mouseScrollEvent() + * instead. + */ + WheelDown CORRADE_DEPRECATED_ENUM("implement mouseScrollEvent() instead") = 5 + #endif }; /** @brief Button */ @@ -1062,7 +1096,7 @@ class AbstractXApplication::MouseEvent: public AbstractXApplication::InputEvent /** @brief Mouse move event -@see @ref MouseEvent, @ref mouseMoveEvent() +@see @ref MouseEvent, @ref MouseScrollEvent, @ref mouseMoveEvent() */ class AbstractXApplication::MouseMoveEvent: public AbstractXApplication::InputEvent { public: @@ -1077,6 +1111,33 @@ class AbstractXApplication::MouseMoveEvent: public AbstractXApplication::InputEv const Vector2i _position; }; +/** +@brief Mouse scroll event +@m_since_latest + +@see @ref MouseEvent, @ref MouseMoveEvent, @ref mouseScrollEvent() +*/ +class AbstractXApplication::MouseScrollEvent: public InputEvent { + public: + /** + * @brief Scroll offset + * + * Is always either @cpp -1.0f @ce or @cpp +1.0f @ce. + */ + Vector2 offset() const { return _offset; } + + /** @brief Position */ + Vector2i position() const { return _position; } + + private: + friend AbstractXApplication; + + explicit MouseScrollEvent(const Vector2& offset, const Vector2i& position, unsigned int modifiers): InputEvent{modifiers}, _offset{offset}, _position{position} {} + + const Vector2 _offset; + const Vector2i _position; +}; + }} #else #error this header is available only in the OpenGL build diff --git a/src/Magnum/Platform/Test/AbstractXApplicationTest.cpp b/src/Magnum/Platform/Test/AbstractXApplicationTest.cpp index 8d0646c32..6ae6fc07f 100644 --- a/src/Magnum/Platform/Test/AbstractXApplicationTest.cpp +++ b/src/Magnum/Platform/Test/AbstractXApplicationTest.cpp @@ -253,6 +253,13 @@ struct AbstractXApplicationTest: Platform::Application { Debug{} << "mouse move:" << event.buttons() << event.modifiers() << Debug::packed << event.position(); } + /* Comment out to test the deprecated scroll as press/release reporting */ + #if 1 + void mouseScrollEvent(MouseScrollEvent& event) override { + Debug{} << "mouse scroll:" << event.buttons() << event.modifiers() << Debug::packed << event.offset() << Debug::packed << event.position(); + } + #endif + void keyPressEvent(KeyEvent& event) override { Debug{} << "key press:" << event.key() << int(event.key()) << event.modifiers() << event.buttons() << Debug::packed << event.position(); }