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(); }