From 3981bcf2f433841991ea5e479bda53f60e19119b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 18 Oct 2024 14:06:16 +0200 Subject: [PATCH] Platform: replace MouseScrollEvent with a ScrollEvent with float position. All the new pointer events have float positions, this one was the odd one out. And I didn't like the name anymore, so I took that as an opportunity to change the position() data type without introducing a breaking change for everyone. Another considered change was adding Z offset to it, since HTML5 APIs have that. However, all my googling led to just a single SO question from 2015, where someone said it's for trackballs that can navigate in 3D space. I'm not sure if *scroll* is actually the best way to report those, and since SDL3 didn't bother adding that and neither Android nor WINAPI have anything like that, I'm not bothering either. Unlike the previous commits, this is done for all apps at once, because it's a comparatively simpler change. The only odd one out is AbstractXApplication, where I introduced MouseScrollEvent just a few commits back, so I simply renamed it without leaving a deprecated copy. Then, ScreenedApplication needed some extra logic to handle the case of apps not implementing any scroll event at all. --- doc/changelog.dox | 21 +++-- src/Magnum/Platform/AbstractXApplication.cpp | 12 ++- src/Magnum/Platform/AbstractXApplication.h | 49 +++++----- src/Magnum/Platform/AndroidApplication.h | 2 + src/Magnum/Platform/EmscriptenApplication.cpp | 41 ++++++++- src/Magnum/Platform/EmscriptenApplication.h | 82 ++++++++++++++--- src/Magnum/Platform/GlfwApplication.cpp | 41 ++++++++- src/Magnum/Platform/GlfwApplication.h | 92 ++++++++++++++++--- src/Magnum/Platform/Platform.h | 7 ++ src/Magnum/Platform/Screen.h | 55 ++++++++++- src/Magnum/Platform/ScreenedApplication.h | 33 ++++++- src/Magnum/Platform/ScreenedApplication.hpp | 54 +++++++++-- src/Magnum/Platform/Sdl2Application.cpp | 44 ++++++++- src/Magnum/Platform/Sdl2Application.h | 84 ++++++++++++++--- .../Test/AbstractXApplicationTest.cpp | 4 +- .../Test/EmscriptenApplicationTest.cpp | 8 +- .../Platform/Test/GlfwApplicationTest.cpp | 8 +- .../Platform/Test/Sdl2ApplicationTest.cpp | 8 +- 18 files changed, 529 insertions(+), 116 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 910b84a85..2ba29a20c 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -810,8 +810,8 @@ See also: events themselves, which happen for example when moving windows across displays with different DPI. - Added more keys to @ref Platform::AbstractXApplication::KeyEvent::Key and - implemented @ref Platform::AbstractXApplication::mouseScrollEvent() for - better consistency with other application implementations + implemented @ref Platform::AbstractXApplication::scrollEvent() for better + consistency with other application implementations @subsubsection changelog-latest-changes-scenegraph SceneGraph library @@ -1391,13 +1391,16 @@ See also: @relativeref{Platform::Sdl2Application,setMinimalLoopPeriod(Nanoseconds)} - @cpp Platform::Sdl2Application::mousePressEvent() @ce, @cpp mouseReleaseEvent() @ce, @cpp mouseMoveEvent() @ce, - @cpp MouseEvent @ce and @cpp MouseMoveEvent @ce are deprecated in favor of - new @ref Platform::Sdl2Application::pointerPressEvent(), + @cpp mouseScrollEvent() @ce, @cpp MouseEvent @ce. @cpp MouseMoveEvent @ce + and @cpp MouseScrollEvent @ce are deprecated in favor of new + @ref Platform::Sdl2Application::pointerPressEvent(), @relativeref{Platform::Sdl2Application,pointerReleaseEvent()}, @relativeref{Platform::Sdl2Application,pointerMoveEvent()}, - @relativeref{Platform::Sdl2Application,PointerEvent} and - @relativeref{Platform::Sdl2Application,PointerMoveEvent} APIs that provide - a better abstraction over general pointer input, not just a mouse alone. + @relativeref{Platform::Sdl2Application,scrollEvent()}, + @relativeref{Platform::Sdl2Application,PointerEvent}, + @relativeref{Platform::Sdl2Application,PointerMoveEvent} and + @relativeref{Platform::Sdl2Application,ScrollEvent} APIs that provide a + better abstraction over general pointer input, not just a mouse alone. The same change is done in @ref Platform::AbstractXApplication, @ref Platform::AndroidApplication, @ref Platform::EmscriptenApplication, @ref Platform::GlfwApplication and the @@ -1405,8 +1408,8 @@ See also: wrappers as well. - @cpp Platform::AbstractXApplication::MouseEvent::Button::WheelUp @ce 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. + @ref Platform::AbstractXApplication::scrollEvent(). 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 1eed0d9bf..21ff9b22e 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -206,11 +206,11 @@ bool AbstractXApplication::mainLoopIteration() { 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}; + ScrollEvent e{Vector2::yAxis(event.xbutton.button == 4 ? 1.0f : -1.0f), {Float(event.xbutton.x), Float(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); + scrollEvent(e); } else { const Pointer pointer = buttonToPointer(event.xbutton.button); Pointers pointers = buttonsToPointers(event.xbutton.state); @@ -360,10 +360,12 @@ void AbstractXApplication::mouseMoveEvent(MouseMoveEvent&) {} CORRADE_IGNORE_DEPRECATED_POP #endif -void AbstractXApplication::mouseScrollEvent(MouseScrollEvent& event) { +void AbstractXApplication::scrollEvent(ScrollEvent& 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()}; + /* The positions are reported in integers in the first place, no need to + round anything */ + MouseEvent e{event.offset().y() > 0.0f ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, event._modifiers, Vector2i{event.position()}}; mousePressEvent(e); mouseReleaseEvent(e); CORRADE_IGNORE_DEPRECATED_POP @@ -384,7 +386,7 @@ AbstractXApplication::Pointers AbstractXApplication::KeyEvent::pointers() const return buttonsToPointers(_modifiers); } -AbstractXApplication::Pointers AbstractXApplication::MouseScrollEvent::pointers() const { +AbstractXApplication::Pointers AbstractXApplication::ScrollEvent::pointers() const { return buttonsToPointers(_modifiers); } diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index 22f1a42c3..ac149cb0d 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -63,6 +63,7 @@ typedef int Bool; #include "Magnum/Magnum.h" #include "Magnum/Tags.h" #include "Magnum/Math/Vector2.h" +#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/GLContext.h" #ifdef MAGNUM_BUILD_DEPRECATED @@ -110,7 +111,7 @@ class AbstractXApplication { class MouseEvent; class MouseMoveEvent; #endif - class MouseScrollEvent; + class ScrollEvent; /* The damn thing cannot handle forward enum declarations */ #ifndef DOXYGEN_GENERATING_OUTPUT @@ -122,7 +123,7 @@ class AbstractXApplication { * @m_since_latest * * @see @ref KeyEvent::pointers(), @ref PointerMoveEvent::pointers(), - * @ref MouseScrollEvent::pointers() + * @ref ScrollEvent::pointers() */ typedef Containers::EnumSet Pointers; @@ -403,7 +404,7 @@ class AbstractXApplication { * @ref mouseReleaseEvent() with @ref MouseEvent::Button::WheelDown and * @ref MouseEvent::Button::WheelUp. */ - virtual void mouseScrollEvent(MouseScrollEvent& event); + virtual void scrollEvent(ScrollEvent& event); /* Since 1.8.17, the original short-hand group closing doesn't work anymore. FFS. */ @@ -425,6 +426,7 @@ class AbstractXApplication { /* Calls the base pointer*Event() in order to delegate to deprecated mouse events */ template friend class BasicScreenedApplication; + template friend struct Implementation::ApplicationScrollEventMixin; #endif enum class Flag: unsigned int { @@ -457,7 +459,7 @@ class AbstractXApplication { @see @ref Pointers, @ref KeyEvent::pointers(), @ref PointerEvent::pointer(), @ref PointerMoveEvent::pointer(), @ref PointerMoveEvent::pointers(), - @ref MouseScrollEvent::pointers() + @ref ScrollEvent::pointers() */ enum class AbstractXApplication::Pointer: UnsignedByte { /** Left mouse button. Corresponds to `Button1` / `Button1Mask`. */ @@ -688,10 +690,9 @@ class AbstractXApplication::ViewportEvent { /** @brief Base for input events -@see @ref KeyEvent, @ref PointerEvent, @ref PointerMoveEvent, - @ref MouseScrollEvent, @ref keyPressEvent(), @ref keyReleaseEvent(), - @ref pointerPressEvent(), @ref pointerReleaseEvent(), - @ref pointerMoveEvent(), @ref mouseScrollEvent() +@see @ref KeyEvent, @ref PointerEvent, @ref PointerMoveEvent, @ref ScrollEvent, + @ref keyPressEvent(), @ref keyReleaseEvent(), @ref pointerPressEvent(), + @ref pointerReleaseEvent(), @ref pointerMoveEvent(), @ref scrollEvent() */ class AbstractXApplication::InputEvent { public: @@ -1236,7 +1237,7 @@ class AbstractXApplication::PointerEvent: public InputEvent { @ref pointerReleaseEvent() instead, which is a better abstraction for covering both mouse and touch / pen input. -@see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(), +@see @ref MouseMoveEvent, @ref ScrollEvent, @ref mousePressEvent(), @ref mouseReleaseEvent() */ class CORRADE_DEPRECATED("use PointerEvent, pointerPressEvent() and pointerReleaseEvent() instead") AbstractXApplication::MouseEvent: public AbstractXApplication::InputEvent { @@ -1254,17 +1255,15 @@ class CORRADE_DEPRECATED("use PointerEvent, pointerPressEvent() and pointerRelea #ifdef MAGNUM_BUILD_DEPRECATED /** * Wheel up - * @m_deprecated_since_latest Implement @ref mouseScrollEvent() - * instead. + * @m_deprecated_since_latest Implement @ref scrollEvent() instead. */ - WheelUp CORRADE_DEPRECATED_ENUM("implement mouseScrollEvent() instead") = 4, + WheelUp CORRADE_DEPRECATED_ENUM("implement scrollEvent() instead") = 4, /** * Wheel down - * @m_deprecated_since_latest Implement @ref mouseScrollEvent() - * instead. + * @m_deprecated_since_latest Implement @ref scrollEvent() instead. */ - WheelDown CORRADE_DEPRECATED_ENUM("implement mouseScrollEvent() instead") = 5 + WheelDown CORRADE_DEPRECATED_ENUM("implement scrollEvent() instead") = 5 #endif }; @@ -1348,7 +1347,7 @@ class AbstractXApplication::PointerMoveEvent: public InputEvent { @ref pointerMoveEvent() instead, which is a better abstraction for covering both mouse and touch / pen input. -@see @ref MouseEvent, @ref MouseScrollEvent, @ref mouseMoveEvent() +@see @ref MouseEvent, @ref ScrollEvent, @ref mouseMoveEvent() */ class CORRADE_DEPRECATED("use PointerMoveEvent and pointerMoveEvent() instead") AbstractXApplication::MouseMoveEvent: public AbstractXApplication::InputEvent { public: @@ -1365,12 +1364,12 @@ class CORRADE_DEPRECATED("use PointerMoveEvent and pointerMoveEvent() instead") #endif /** -@brief Mouse scroll event +@brief Scroll event @m_since_latest -@see @ref PointerEvent, @ref PointerMoveEvent, @ref mouseScrollEvent() +@see @ref PointerEvent, @ref PointerMoveEvent, @ref scrollEvent() */ -class AbstractXApplication::MouseScrollEvent: public InputEvent { +class AbstractXApplication::ScrollEvent: public InputEvent { public: /** * @brief Scroll offset @@ -1379,8 +1378,12 @@ class AbstractXApplication::MouseScrollEvent: public InputEvent { */ Vector2 offset() const { return _offset; } - /** @brief Position */ - Vector2i position() const { return _position; } + /** + * @brief Position + * + * For mouse input the position is always reported in whole pixels. + */ + Vector2 position() const { return _position; } /** * @brief Pointer types pressed in this event @@ -1393,10 +1396,10 @@ class AbstractXApplication::MouseScrollEvent: public InputEvent { private: friend AbstractXApplication; - explicit MouseScrollEvent(const Vector2& offset, const Vector2i& position, unsigned int modifiers): InputEvent{modifiers}, _offset{offset}, _position{position} {} + explicit ScrollEvent(const Vector2& offset, const Vector2& position, unsigned int modifiers): InputEvent{modifiers}, _offset{offset}, _position{position} {} const Vector2 _offset; - const Vector2i _position; + const Vector2 _position; }; }} diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index 9e5534809..f8663d00d 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -499,6 +499,8 @@ class AndroidApplication { /* Calls the base pointer*Event() in order to delegate to deprecated mouse events */ template friend class BasicScreenedApplication; + /* Not ApplicationScrollEventMixin, as this class doesn't have the + deprecated mouseScrollEvent() */ #endif struct LogOutput; diff --git a/src/Magnum/Platform/EmscriptenApplication.cpp b/src/Magnum/Platform/EmscriptenApplication.cpp index 206f1a609..4ea6a96ab 100644 --- a/src/Magnum/Platform/EmscriptenApplication.cpp +++ b/src/Magnum/Platform/EmscriptenApplication.cpp @@ -614,8 +614,8 @@ void EmscriptenApplication::setupCallbacks(bool resizable) { emscripten_set_wheel_callback(_canvasTarget.data(), this, false, ([](int, const EmscriptenWheelEvent* event, void* userData) -> EM_BOOL { - MouseScrollEvent e{*event}; - static_cast(userData)->mouseScrollEvent(e); + ScrollEvent e{*event}; + static_cast(userData)->scrollEvent(e); return e.isAccepted(); })); @@ -854,7 +854,23 @@ void EmscriptenApplication::mouseMoveEvent(MouseMoveEvent&) {} CORRADE_IGNORE_DEPRECATED_POP #endif +void EmscriptenApplication::scrollEvent(ScrollEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + MouseScrollEvent mouseEvent{event.event()}; + mouseScrollEvent(mouseEvent); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED +CORRADE_IGNORE_DEPRECATED_PUSH void EmscriptenApplication::mouseScrollEvent(MouseScrollEvent&) {} +CORRADE_IGNORE_DEPRECATED_POP +#endif + void EmscriptenApplication::textInputEvent(TextInputEvent&) {} #ifdef MAGNUM_TARGET_GL @@ -967,7 +983,7 @@ EmscriptenApplication::MouseMoveEvent::Modifiers EmscriptenApplication::MouseMov } #endif -Vector2 EmscriptenApplication::MouseScrollEvent::offset() const { +Vector2 EmscriptenApplication::ScrollEvent::offset() const { /* From emscripten's Browser.getMouseWheelDelta() function in library_browser.js: @@ -980,6 +996,24 @@ Vector2 EmscriptenApplication::MouseScrollEvent::offset() const { return {f*Float(_event.deltaX), f*Float(_event.deltaY)}; } +Vector2 EmscriptenApplication::ScrollEvent::position() const { + /* Relies on the target being the canvas, which should be always true for + mouse events */ + return {Float(_event.mouse.targetX), Float(_event.mouse.targetY)}; +} + +EmscriptenApplication::InputEvent::Modifiers EmscriptenApplication::ScrollEvent::modifiers() const { + return eventModifiers(_event.mouse); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +Vector2 EmscriptenApplication::MouseScrollEvent::offset() const { + const Float f = (_event.deltaMode == DOM_DELTA_PIXEL) ? -0.01f : + ((_event.deltaMode == DOM_DELTA_LINE) ? -1.0f/3.0f : -80.0f); + + return {f*Float(_event.deltaX), f*Float(_event.deltaY)}; +} + Vector2i EmscriptenApplication::MouseScrollEvent::position() const { /* Relies on the target being the canvas, which should be always true for mouse events. The targetX and targetY variables used to be a `long` @@ -990,6 +1024,7 @@ Vector2i EmscriptenApplication::MouseScrollEvent::position() const { EmscriptenApplication::InputEvent::Modifiers EmscriptenApplication::MouseScrollEvent::modifiers() const { return eventModifiers(_event.mouse); } +#endif Key EmscriptenApplication::KeyEvent::key() const { return toKey(_event.key, _event.code); diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index 70b08ca34..222030ef8 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -298,11 +298,12 @@ class EmscriptenApplication { class InputEvent; class PointerEvent; class PointerMoveEvent; + class ScrollEvent; #ifdef MAGNUM_BUILD_DEPRECATED class MouseEvent; class MouseMoveEvent; - #endif class MouseScrollEvent; + #endif class KeyEvent; class TextInputEvent; @@ -910,12 +911,29 @@ class EmscriptenApplication { #endif /** - * @brief Mouse scroll event + * @brief Scroll event + * @m_since_latest * * Called when a scrolling device is used (mouse wheel or scrolling - * area on a touchpad). Default implementation does nothing. + * area on a touchpad). + * + * On builds with @ref MAGNUM_BUILD_DEPRECATED enabled, default + * implementation delegates to @ref mouseScrollEvent(). On builds with + * deprecated functionality disabled, default implementation does + * nothing. */ - virtual void mouseScrollEvent(MouseScrollEvent& event); + virtual void scrollEvent(ScrollEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Mouse move event + * @m_deprecated_since_latest Use @ref scrollEvent() instead, which + * isn't semantically tied to just a mouse. + * + * Default implementation does nothing. + */ + virtual CORRADE_DEPRECATED("use scrollEvent() instead") void mouseScrollEvent(MouseScrollEvent& event); + #endif /* Since 1.8.17, the original short-hand group closing doesn't work anymore. FFS. */ @@ -984,6 +1002,7 @@ class EmscriptenApplication { /* Calls the base pointer*Event() in order to delegate to deprecated mouse events */ template friend class BasicScreenedApplication; + template friend struct Implementation::ApplicationScrollEventMixin; #endif enum class Flag: UnsignedByte; @@ -1572,10 +1591,9 @@ class EmscriptenApplication::ViewportEvent { /** @brief Base for input events -@see @ref KeyEvent, @ref PointerEvent, @ref PointerMoveEvent, - @ref MouseScrollEvent, @ref keyPressEvent(), @ref keyReleaseEvent(), - @ref pointerPressEvent(), @ref pointerReleaseEvent(), - @ref pointerMoveEvent(), @ref mouseScrollEvent() +@see @ref KeyEvent, @ref PointerEvent, @ref PointerMoveEvent, @ref ScrollEvent, + @ref keyPressEvent(), @ref keyReleaseEvent(), @ref pointerPressEvent(), + @ref pointerReleaseEvent(), @ref pointerMoveEvent(), @ref scrollEvent() */ class EmscriptenApplication::InputEvent { public: @@ -1585,7 +1603,7 @@ class EmscriptenApplication::InputEvent { * @see @ref Modifiers, @ref KeyEvent::modifiers(), * @ref PointerEvent::modifiers(), * @ref PointerMoveEvent::modifiers(), - * @ref MouseScrollEvent::modifiers() + * @ref ScrollEvent::modifiers() */ enum class Modifier: Int { /** @@ -1622,7 +1640,7 @@ class EmscriptenApplication::InputEvent { * * @see @ref KeyEvent::modifiers(), @ref PointerEvent::modifiers(), * @ref PointerMoveEvent::modifiers(), - * @ref MouseScrollEvent::modifiers() + * @ref ScrollEvent::modifiers() */ typedef Containers::EnumSet Modifiers; @@ -1665,7 +1683,7 @@ CORRADE_ENUMSET_OPERATORS(EmscriptenApplication::InputEvent::Modifiers) @brief Pointer event @m_since_latest -@see @ref PointerMoveEvent, @ref MouseScrollEvent, @ref pointerPressEvent(), +@see @ref PointerMoveEvent, @ref ScrollEvent, @ref pointerPressEvent(), @ref pointerReleaseEvent() */ class EmscriptenApplication::PointerEvent: public InputEvent { @@ -1763,7 +1781,7 @@ class CORRADE_DEPRECATED("use PointerEvent, pointerPressEvent() and pointerRelea @brief Pointer move event @m_since_latest -@see @ref PointerEvent, @ref MouseScrollEvent, @ref pointerMoveEvent() +@see @ref PointerEvent, @ref ScrollEvent, @ref pointerMoveEvent() */ class EmscriptenApplication::PointerMoveEvent: public InputEvent { public: @@ -1902,12 +1920,47 @@ CORRADE_ENUMSET_OPERATORS(EmscriptenApplication::MouseMoveEvent::Buttons) CORRADE_IGNORE_DEPRECATED_POP #endif +/** +@brief Scroll event +@m_since_latest + +@see @ref PointerEvent, @ref PointerMoveEvent, @ref scrollEvent() +*/ +class EmscriptenApplication::ScrollEvent: public EmscriptenApplication::InputEvent { + public: + /** @brief Scroll offset */ + Vector2 offset() const; + + /** + * @brief Position + * + * The position is always reported in whole pixels. + */ + Vector2 position() const; + + /** @brief Modifiers */ + Modifiers modifiers() const; + + /** @brief Underlying Emscripten event */ + const EmscriptenWheelEvent& event() const { return _event; } + + private: + friend EmscriptenApplication; + + explicit ScrollEvent(const EmscriptenWheelEvent& event): _event(event) {} + + const EmscriptenWheelEvent& _event; +}; + +#ifdef MAGNUM_BUILD_DEPRECATED /** @brief Mouse scroll event +@m_deprecated_since_latest Use @ref ScrollEvent and @ref scrollEvent() instead, + which isn't semantically tied to just a mouse. -@see @ref PointerEvent, @ref PointerMoveEvent, @ref mouseScrollEvent() +@see @ref MouseEvent, @ref MouseMoveEvent, @ref mouseScrollEvent() */ -class EmscriptenApplication::MouseScrollEvent: public EmscriptenApplication::InputEvent { +class CORRADE_DEPRECATED("use ScrollEvent and scrollEvent() instead") EmscriptenApplication::MouseScrollEvent: public InputEvent { public: /** @brief Scroll offset */ Vector2 offset() const; @@ -1928,6 +1981,7 @@ class EmscriptenApplication::MouseScrollEvent: public EmscriptenApplication::Inp const EmscriptenWheelEvent& _event; }; +#endif /** @brief Key event diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 1865e412a..441a7ac59 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -727,8 +727,8 @@ void GlfwApplication::setupCallbacks() { app.pointerMoveEvent(e); }); glfwSetScrollCallback(_window, [](GLFWwindow* window, double xoffset, double yoffset) { - MouseScrollEvent e(window, Vector2{Float(xoffset), Float(yoffset)}); - static_cast(glfwGetWindowUserPointer(window))->mouseScrollEvent(e); + ScrollEvent e{window, {Float(xoffset), Float(yoffset)}}; + static_cast(glfwGetWindowUserPointer(window))->scrollEvent(e); }); glfwSetCharCallback(_window, [](GLFWwindow* window, unsigned int codepoint) { auto& app = *static_cast(glfwGetWindowUserPointer(window)); @@ -1072,7 +1072,23 @@ void GlfwApplication::mouseMoveEvent(MouseMoveEvent&) {} CORRADE_IGNORE_DEPRECATED_POP #endif +void GlfwApplication::scrollEvent(ScrollEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + MouseScrollEvent mouseEvent{_window, event.offset()}; + mouseScrollEvent(mouseEvent); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED +CORRADE_IGNORE_DEPRECATED_PUSH void GlfwApplication::mouseScrollEvent(MouseScrollEvent&) {} +CORRADE_IGNORE_DEPRECATED_POP +#endif + void GlfwApplication::textInputEvent(TextInputEvent&) {} bool GlfwApplication::isTextInputActive() const { @@ -1153,6 +1169,21 @@ auto GlfwApplication::MouseMoveEvent::modifiers() -> Modifiers { CORRADE_IGNORE_DEPRECATED_POP #endif +auto GlfwApplication::ScrollEvent::modifiers() -> Modifiers { + if(!_modifiers) _modifiers = currentGlfwModifiers(_window); + return *_modifiers; +} +Vector2 GlfwApplication::ScrollEvent::position() { + if(!_position) { + Vector2d position; + glfwGetCursorPos(_window, &position.x(), &position.y()); + _position = Vector2{position}; + } + return *_position; +} + +#ifdef MAGNUM_BUILD_DEPRECATED +CORRADE_IGNORE_DEPRECATED_PUSH Vector2i GlfwApplication::MouseScrollEvent::position() { if(!_position) { Vector2d position; @@ -1167,11 +1198,13 @@ auto GlfwApplication::MouseScrollEvent::modifiers() -> Modifiers { if(!_modifiers) _modifiers = currentGlfwModifiers(_window); return *_modifiers; } +CORRADE_IGNORE_DEPRECATED_POP +#endif /* On MSVC 2017, deprecation warning suppression doesn't work on virtual function overrides, so ScreenedApplication overriding mousePressEvent(), - mouseReleaseEvent(), and mouseMoveEvent() causes warnings. Disable them at a - higher level instead. */ + mouseReleaseEvent() mouseMoveEvent() and mouseScrollEvent() causes warnings. + Disable them at a higher level instead. */ #if defined(MAGNUM_BUILD_DEPRECATED) && defined(CORRADE_TARGET_MSVC) && !defined(CORRADE_TARGET_CLANG) && _MSC_VER < 1920 CORRADE_IGNORE_DEPRECATED_PUSH #endif diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index d025b4359..f909c2c22 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -180,11 +180,12 @@ class GlfwApplication { class KeyEvent; class PointerEvent; class PointerMoveEvent; + class ScrollEvent; #ifdef MAGNUM_BUILD_DEPRECATED class MouseEvent; class MouseMoveEvent; - #endif class MouseScrollEvent; + #endif class TextInputEvent; /* The damn thing cannot handle forward enum declarations */ @@ -776,8 +777,30 @@ class GlfwApplication { virtual CORRADE_DEPRECATED("use pointerMoveEvent() instead") void mouseMoveEvent(MouseMoveEvent& event); #endif - /** @copydoc Sdl2Application::mouseScrollEvent() */ - virtual void mouseScrollEvent(MouseScrollEvent& event); + /** + * @brief 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 mouseScrollEvent(). On builds with + * deprecated functionality disabled, default implementation does + * nothing. + */ + virtual void scrollEvent(ScrollEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Mouse move event + * @m_deprecated_since_latest Use @ref scrollEvent() instead, which + * isn't semantically tied to just a mouse. + * + * Default implementation does nothing. + */ + virtual CORRADE_DEPRECATED("use scrollEvent() instead") void mouseScrollEvent(MouseScrollEvent& event); + #endif /* Since 1.8.17, the original short-hand group closing doesn't work anymore. FFS. */ @@ -870,6 +893,7 @@ class GlfwApplication { /* Calls the base pointer*Event() in order to delegate to deprecated mouse events */ template friend class BasicScreenedApplication; + template friend struct Implementation::ApplicationScrollEventMixin; #endif enum class Flag: UnsignedByte; @@ -1696,10 +1720,9 @@ class GlfwApplication::ViewportEvent { /** @brief Base for input events -@see @ref KeyEvent, @ref PointerEvent, @ref PointerMoveEvent, - @ref MouseScrollEvent, @ref keyPressEvent(), @ref keyReleaseEvent(), - @ref pointerPressEvent(), @ref pointerReleaseEvent(), - @ref pointerMoveEvent(), @ref mouseScrollEvent() +@see @ref KeyEvent, @ref PointerEvent, @ref PointerMoveEvent, @ref ScrollEvent, + @ref keyPressEvent(), @ref keyReleaseEvent(), @ref pointerPressEvent(), + @ref pointerReleaseEvent(), @ref pointerMoveEvent(), @ref scrollEvent() */ class GlfwApplication::InputEvent { public: @@ -1709,7 +1732,7 @@ class GlfwApplication::InputEvent { * @see @ref Modifiers, @ref KeyEvent::modifiers(), * @ref PointerEvent::modifiers(), * @ref PointerMoveEvent::modifiers(), - * @ref MouseScrollEvent::modifiers() + * @ref ScrollEvent::modifiers() */ enum class Modifier: Int { /** @@ -1746,7 +1769,7 @@ class GlfwApplication::InputEvent { * * @see @ref KeyEvent::modifiers(), @ref PointerEvent::modifiers(), * @ref PointerMoveEvent::modifiers(), - * @ref MouseScrollEvent::modifiers() + * @ref ScrollEvent::modifiers() */ typedef Containers::EnumSet Modifiers; @@ -2092,7 +2115,7 @@ class GlfwApplication::KeyEvent: public GlfwApplication::InputEvent { @brief Pointer event @m_since_latest -@see @ref PointerMoveEvent, @ref MouseScrollEvent, @ref pointerPressEvent(), +@see @ref PointerMoveEvent, @ref ScrollEvent, @ref pointerPressEvent(), @ref pointerReleaseEvent() */ class GlfwApplication::PointerEvent: public InputEvent { @@ -2189,7 +2212,7 @@ class CORRADE_DEPRECATED("use PointerEvent, pointerPressEvent() and pointerRelea @brief Pointer move event @m_since_latest -@see @ref PointerEvent, @ref MouseScrollEvent, @ref pointerMoveEvent() +@see @ref PointerEvent, @ref ScrollEvent, @ref pointerMoveEvent() */ class GlfwApplication::PointerMoveEvent: public InputEvent { public: @@ -2339,12 +2362,54 @@ CORRADE_ENUMSET_OPERATORS(GlfwApplication::MouseMoveEvent::Buttons) CORRADE_IGNORE_DEPRECATED_POP #endif +/** +@brief Scroll event +@m_since_latest + +@see @ref PointerEvent, @ref PointerMoveEvent, @ref scrollEvent() +*/ +class GlfwApplication::ScrollEvent: public InputEvent { + public: + /** @brief Scroll offset */ + Vector2 offset() const { return _offset; } + + /** + * @brief Position + * + * May return fractional values for example on HiDPI systems where + * window size is smaller than actual framebuffer size. Use + * @ref Math::round() to snap them to the nearest window pixel. Lazily + * populated on first request. + */ + Vector2 position(); + + /** + * @brief Modifiers + * + * Lazily populated on first request. + */ + Modifiers modifiers(); + + private: + friend GlfwApplication; + + explicit ScrollEvent(GLFWwindow* window, const Vector2& offset): _window{window}, _offset{offset} {} + + GLFWwindow* const _window; + const Vector2 _offset; + Containers::Optional _position; + Containers::Optional _modifiers; +}; + +#ifdef MAGNUM_BUILD_DEPRECATED /** @brief Mouse scroll event +@m_deprecated_since_latest Use @ref ScrollEvent and @ref scrollEvent() instead, + which isn't semantically tied to just a mouse. -@see @ref PointerEvent, @ref PointerMoveEvent, @ref mouseScrollEvent() +@see @ref MouseEvent, @ref MouseMoveEvent, @ref mouseScrollEvent() */ -class GlfwApplication::MouseScrollEvent: public GlfwApplication::InputEvent { +class CORRADE_DEPRECATED("use ScrollEvent and scrollEvent() instead") GlfwApplication::MouseScrollEvent: public GlfwApplication::InputEvent { public: /** @brief Scroll offset */ Vector2 offset() const { return _offset; } @@ -2373,6 +2438,7 @@ class GlfwApplication::MouseScrollEvent: public GlfwApplication::InputEvent { Containers::Optional _position; Containers::Optional _modifiers; }; +#endif /** @brief Text input event diff --git a/src/Magnum/Platform/Platform.h b/src/Magnum/Platform/Platform.h index 92850798c..87342e4a9 100644 --- a/src/Magnum/Platform/Platform.h +++ b/src/Magnum/Platform/Platform.h @@ -37,6 +37,13 @@ namespace Magnum { namespace Platform { #ifndef DOXYGEN_GENERATING_OUTPUT template class BasicScreen; template class BasicScreenedApplication; +/* For ScreenedApplication backwards compatibility with mouseScrollEvent() + delegated from scrollEvent(), remove once gone */ +#ifdef MAGNUM_BUILD_DEPRECATED +namespace Implementation { + template struct ApplicationScrollEventMixin; +} +#endif #ifdef MAGNUM_TARGET_GL class GLContext; diff --git a/src/Magnum/Platform/Screen.h b/src/Magnum/Platform/Screen.h index 8e4b40490..b9289df5c 100644 --- a/src/Magnum/Platform/Screen.h +++ b/src/Magnum/Platform/Screen.h @@ -62,16 +62,33 @@ template class ScreenKeyEventMixin { virtual void keyReleaseEvent(KeyEvent& event); }; +template class ScreenScrollEventMixin {}; +template class ScreenScrollEventMixin { + public: + typedef typename BasicScreenedApplication::ScrollEvent ScrollEvent; + + private: + friend ApplicationScrollEventMixin; + + virtual void scrollEvent(ScrollEvent& event); +}; + +#ifdef MAGNUM_BUILD_DEPRECATED template class ScreenMouseScrollEventMixin {}; template class ScreenMouseScrollEventMixin { public: - typedef typename BasicScreenedApplication::MouseScrollEvent MouseScrollEvent; + CORRADE_IGNORE_DEPRECATED_PUSH + typedef CORRADE_DEPRECATED("use ScrollEvent and scrollEvent() instead") typename BasicScreenedApplication::MouseScrollEvent MouseScrollEvent; + CORRADE_IGNORE_DEPRECATED_POP private: friend ApplicationMouseScrollEventMixin; - virtual void mouseScrollEvent(MouseScrollEvent& event); + CORRADE_IGNORE_DEPRECATED_PUSH + virtual CORRADE_DEPRECATED("use scrollEvent() instead") void mouseScrollEvent(MouseScrollEvent& event); + CORRADE_IGNORE_DEPRECATED_POP }; +#endif template class ScreenTextInputEventMixin {}; template class ScreenTextInputEventMixin { @@ -123,7 +140,10 @@ The following specialization are explicitly compiled into each particular template class BasicScreen: private Containers::LinkedListItem, BasicScreenedApplication>, public Implementation::ScreenKeyEventMixin::value>, + public Implementation::ScreenScrollEventMixin::value>, + #ifdef MAGNUM_BUILD_DEPRECATED public Implementation::ScreenMouseScrollEventMixin::value>, + #endif public Implementation::ScreenTextInputEventMixin::value>, public Implementation::ScreenTextEditingEventMixin::value> { @@ -229,14 +249,27 @@ template class BasicScreen: #endif #ifdef DOXYGEN_GENERATING_OUTPUT + /** + * @brief Scroll event + * @m_since_latest + * + * Defined only if the application has a + * @relativeref{Sdl2Application,ScrollEvent}. + */ + typedef typename BasicScreenedApplication::ScrollEvent ScrollEvent; + + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Mouse scroll event - * @m_since{2019,10} + * @m_deprecated_since_latest Use @ref ScrollEvent and + * @ref scrollEvent() instead, which isn't semantically tied to + * just a mouse. * * Defined only if the application has a * @ref Sdl2Application::MouseScrollEvent "MouseScrollEvent". */ typedef typename BasicScreenedApplication::MouseScrollEvent MouseScrollEvent; + #endif /** * @brief Text input event @@ -522,9 +555,22 @@ template class BasicScreen: #endif #ifdef DOXYGEN_GENERATING_OUTPUT + /** + * @brief Scroll event + * @m_since_latest + * + * Called when @ref PropagatedEvent::Input is enabled and mouse wheel + * is rotated. See @ref Sdl2Application::scrollEvent() "*Application::scrollEvent()" + * for more information. Defined only if the application has a + * @ref Sdl2Application::ScrollEvent "ScrollEvent". + */ + virtual void scrollEvent(ScrollEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Mouse scroll event - * @m_since{2019,10} + * @m_deprecated_since_latest Use @ref scrollEvent() instead, which + * isn't semantically tied to just a mouse. * * Called when @ref PropagatedEvent::Input is enabled and mouse wheel * is rotated. See @ref Sdl2Application::mouseScrollEvent() "*Application::mouseScrollEvent()" @@ -533,6 +579,7 @@ template class BasicScreen: */ virtual void mouseScrollEvent(MouseScrollEvent& event); #endif + #endif /* Since 1.8.17, the original short-hand group closing doesn't work anymore. FFS. */ diff --git a/src/Magnum/Platform/ScreenedApplication.h b/src/Magnum/Platform/ScreenedApplication.h index 3487164f9..1b0cb6a4b 100644 --- a/src/Magnum/Platform/ScreenedApplication.h +++ b/src/Magnum/Platform/ScreenedApplication.h @@ -41,7 +41,10 @@ namespace Magnum { namespace Platform { namespace Implementation { CORRADE_HAS_TYPE(HasKeyEvent, typename T::KeyEvent); +CORRADE_HAS_TYPE(HasScrollEvent, typename T::ScrollEvent); +#ifdef MAGNUM_BUILD_DEPRECATED CORRADE_HAS_TYPE(HasMouseScrollEvent, typename T::MouseScrollEvent); +#endif CORRADE_HAS_TYPE(HasTextInputEvent, typename T::TextInputEvent); CORRADE_HAS_TYPE(HasTextEditingEvent, typename T::TextEditingEvent); @@ -60,9 +63,22 @@ template struct ApplicationKeyEventMixin { void callKeyReleaseEvent(typename Application::KeyEvent& event, Containers::LinkedList>& screens); }; -/* Calls into the screen in case the application has a mouseScrollEvent(), - otherwise provides a dummy virtual so the application can unconditionally - override */ +/* Calls into the screen in case the application has a scrollEvent(), otherwise + provides a dummy virtual so the application can unconditionally override */ +template struct ApplicationScrollEventMixin { + typedef int ScrollEvent; + virtual void scrollEvent(ScrollEvent&) = 0; + + void callScrollEvent(Application&, ScrollEvent&, Containers::LinkedList>&); +}; +template struct ApplicationScrollEventMixin { + void callScrollEvent(Application& application, typename Application::ScrollEvent& event, Containers::LinkedList>& screens); +}; + +#ifdef MAGNUM_BUILD_DEPRECATED +/* Calls into the screen in case the application has a (deprecated) + mouseScrollEvent(), otherwise provides a dummy virtual so the application + can unconditionally override */ template struct ApplicationMouseScrollEventMixin { typedef int MouseScrollEvent; virtual void mouseScrollEvent(MouseScrollEvent&) = 0; @@ -70,8 +86,11 @@ template struct ApplicationMouseScrollEventMixin { void callMouseScrollEvent(MouseScrollEvent&, Containers::LinkedList>&); }; template struct ApplicationMouseScrollEventMixin { + CORRADE_IGNORE_DEPRECATED_PUSH void callMouseScrollEvent(typename Application::MouseScrollEvent& event, Containers::LinkedList>& screens); + CORRADE_IGNORE_DEPRECATED_POP }; +#endif /* Calls into the screen in case the application has a textInputEvent(), otherwise provides a dummy virtual so the application can unconditionally @@ -175,7 +194,10 @@ template class BasicScreenedApplication: public Application, private Containers::LinkedList>, private Implementation::ApplicationKeyEventMixin::value>, + private Implementation::ApplicationScrollEventMixin::value>, + #ifdef MAGNUM_BUILD_DEPRECATED private Implementation::ApplicationMouseScrollEventMixin::value>, + #endif private Implementation::ApplicationTextInputEventMixin::value>, private Implementation::ApplicationTextEditingEventMixin::value> { @@ -339,7 +361,12 @@ template class BasicScreenedApplication: doesn't have them, they're overriding a mixin dummy */ void keyPressEvent(typename BasicScreenedApplication::KeyEvent& event) override final; void keyReleaseEvent(typename BasicScreenedApplication::KeyEvent& event) override final; + void scrollEvent(typename BasicScreenedApplication::ScrollEvent& event) override final; + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH void mouseScrollEvent(typename BasicScreenedApplication::MouseScrollEvent& event) override final; + CORRADE_IGNORE_DEPRECATED_POP + #endif void textInputEvent(typename BasicScreenedApplication::TextInputEvent& event) override final; void textEditingEvent(typename BasicScreenedApplication::TextEditingEvent& event) override final; }; diff --git a/src/Magnum/Platform/ScreenedApplication.hpp b/src/Magnum/Platform/ScreenedApplication.hpp index b5688234d..ef23837c7 100644 --- a/src/Magnum/Platform/ScreenedApplication.hpp +++ b/src/Magnum/Platform/ScreenedApplication.hpp @@ -59,6 +59,30 @@ template void ApplicationKeyEventMixin::ca } } +template void ApplicationScrollEventMixin::callScrollEvent(Application&, ScrollEvent&, Containers::LinkedList>&) {} +template void ApplicationScrollEventMixin::callScrollEvent(Application& application, typename Application::ScrollEvent& event, Containers::LinkedList>& screens) { + /* Front-to-back event propagation, stop when the event gets accepted */ + for(BasicScreen* s = screens.first(); s; s = s->nextFartherScreen()) { + if(s->propagatedEvents() & Implementation::PropagatedScreenEvent::Input) { + s->scrollEvent(event); + if(event.isAccepted()) break; + } + } + + #ifdef MAGNUM_BUILD_DEPRECATED + /* If the event wasn't accepted, it's possible that the screens still only + implement the deprecated mouse events. Call into the base + implementation and assume it appropriately delegates to + mouseScrollEvent(). */ + if(!event.isAccepted()) + application.scrollEvent(event); + #else + static_cast(application); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED +CORRADE_IGNORE_DEPRECATED_PUSH template void ApplicationMouseScrollEventMixin::callMouseScrollEvent(MouseScrollEvent&, Containers::LinkedList>&) {} template void ApplicationMouseScrollEventMixin::callMouseScrollEvent(typename Application::MouseScrollEvent& event, Containers::LinkedList>& screens) { /* Front-to-back event propagation, stop when the event gets accepted */ @@ -69,6 +93,8 @@ template void ApplicationMouseScrollEventMixin void ApplicationTextInputEventMixin::callTextInputEvent(TextInputEvent&, Containers::LinkedList>&) {} template void ApplicationTextInputEventMixin::callTextInputEvent(typename Application::TextInputEvent& event, Containers::LinkedList>& screens) { @@ -93,16 +119,16 @@ true>::callTextEditingEvent(typename Application::TextEditingEvent& event, Conta } } -template void ScreenKeyEventMixin::keyPressEvent(KeyEvent&) {} -template void ScreenKeyEventMixin::keyReleaseEvent(KeyEvent&) {} -template void ScreenMouseScrollEventMixin::mouseScrollEvent(MouseScrollEvent&) {} -template void ScreenTextInputEventMixin::textInputEvent(TextInputEvent&) {} -template void ScreenTextEditingEventMixin::textEditingEvent(TextEditingEvent&) {} +template void ScreenKeyEventMixin::keyPressEvent(KeyEvent&) {} +template void ScreenKeyEventMixin::keyReleaseEvent(KeyEvent&) {} +template void ScreenScrollEventMixin::scrollEvent(ScrollEvent&) {} +#ifdef MAGNUM_BUILD_DEPRECATED +CORRADE_IGNORE_DEPRECATED_PUSH +template void ScreenMouseScrollEventMixin::mouseScrollEvent(MouseScrollEvent&) {} +CORRADE_IGNORE_DEPRECATED_POP +#endif +template void ScreenTextInputEventMixin::textInputEvent(TextInputEvent&) {} +template void ScreenTextEditingEventMixin::textEditingEvent(TextEditingEvent&) {} } @@ -324,9 +350,17 @@ template void BasicScreenedApplication::mouseMov CORRADE_IGNORE_DEPRECATED_POP #endif +template void BasicScreenedApplication::scrollEvent(typename BasicScreenedApplication::ScrollEvent& event) { + this->callScrollEvent(*this, event, screens()); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +CORRADE_IGNORE_DEPRECATED_PUSH template void BasicScreenedApplication::mouseScrollEvent(typename BasicScreenedApplication::MouseScrollEvent& event) { this->callMouseScrollEvent(event, screens()); } +CORRADE_IGNORE_DEPRECATED_POP +#endif template void BasicScreenedApplication::textInputEvent(typename BasicScreenedApplication::TextInputEvent& event) { this->callTextInputEvent(event, screens()); diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 76479fa0c..761a98f74 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -1042,8 +1042,8 @@ bool Sdl2Application::mainLoopIteration() { } break; case SDL_MOUSEWHEEL: { - MouseScrollEvent e{event, {Float(event.wheel.x), Float(event.wheel.y)}}; - mouseScrollEvent(e); + ScrollEvent e{event, {Float(event.wheel.x), Float(event.wheel.y)}}; + scrollEvent(e); } break; case SDL_MOUSEMOTION: { @@ -1401,7 +1401,23 @@ void Sdl2Application::mouseMoveEvent(MouseMoveEvent&) {} CORRADE_IGNORE_DEPRECATED_POP #endif +void Sdl2Application::scrollEvent(ScrollEvent& event) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_IGNORE_DEPRECATED_PUSH + MouseScrollEvent mouseEvent{event.event(), event.offset()}; + mouseScrollEvent(mouseEvent); + CORRADE_IGNORE_DEPRECATED_POP + #else + static_cast(event); + #endif +} + +#ifdef MAGNUM_BUILD_DEPRECATED +CORRADE_IGNORE_DEPRECATED_PUSH void Sdl2Application::mouseScrollEvent(MouseScrollEvent&) {} +CORRADE_IGNORE_DEPRECATED_POP +#endif + void Sdl2Application::multiGestureEvent(MultiGestureEvent&) {} void Sdl2Application::textInputEvent(TextInputEvent&) {} void Sdl2Application::textEditingEvent(TextEditingEvent&) {} @@ -1473,6 +1489,23 @@ Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseMoveEvent::modifier CORRADE_IGNORE_DEPRECATED_POP #endif +Vector2 Sdl2Application::ScrollEvent::position() { + if(!_position) { + Vector2i position; + SDL_GetMouseState(&position.x(), &position.y()); + _position = Vector2{position}; + } + return *_position; +} + +Sdl2Application::InputEvent::Modifiers Sdl2Application::ScrollEvent::modifiers() { + if(!_modifiers) + _modifiers = fixedModifiers(Uint16(SDL_GetModState())); + return *_modifiers; +} + +#ifdef MAGNUM_BUILD_DEPRECATED +CORRADE_IGNORE_DEPRECATED_PUSH Vector2i Sdl2Application::MouseScrollEvent::position() { if(_position) return *_position; _position = Vector2i{}; @@ -1484,12 +1517,15 @@ Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseScrollEvent::modifi if(_modifiers) return *_modifiers; return *(_modifiers = fixedModifiers(Uint16(SDL_GetModState()))); } +CORRADE_IGNORE_DEPRECATED_POP +#endif /* WinRT builds by default have deprecation warnings as errors. Combined with a MSVC 2017 bug where deprecation warning suppression doesn't work on virtual function overrides this make the build fail on deprecation warnings due to - ScreenedApplication overriding mousePressEvent(), mouseReleaseEvent() and - mouseMoveEvent(). Disable the warnings at a higher level instead. */ + ScreenedApplication overriding mousePressEvent(), mouseReleaseEvent(), + mouseMoveEvent() and mouseScrollEvent(). Disable the warnings at a higher + level instead. */ #if defined(MAGNUM_BUILD_DEPRECATED) && defined(CORRADE_TARGET_MSVC) && !defined(CORRADE_TARGET_CLANG) && _MSC_VER < 1920 CORRADE_IGNORE_DEPRECATED_PUSH #endif diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 47be1a338..c89e89ac6 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -502,11 +502,12 @@ class Sdl2Application { class KeyEvent; class PointerEvent; class PointerMoveEvent; + class ScrollEvent; #ifdef MAGNUM_BUILD_DEPRECATED class MouseEvent; class MouseMoveEvent; - #endif class MouseScrollEvent; + #endif class MultiGestureEvent; class TextInputEvent; class TextEditingEvent; @@ -1184,12 +1185,29 @@ class Sdl2Application { #endif /** - * @brief Mouse scroll event + * @brief Scroll event + * @m_since_latest * * Called when a scrolling device is used (mouse wheel or scrolling - * area on a touchpad). Default implementation does nothing. + * area on a touchpad). + * + * On builds with @ref MAGNUM_BUILD_DEPRECATED enabled, default + * implementation delegates to @ref mouseScrollEvent(). On builds with + * deprecated functionality disabled, default implementation does + * nothing. + */ + virtual void scrollEvent(ScrollEvent& event); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Mouse move event + * @m_deprecated_since_latest Use @ref scrollEvent() instead, which + * isn't semantically tied to just a mouse. + * + * Default implementation does nothing. */ - virtual void mouseScrollEvent(MouseScrollEvent& event); + virtual CORRADE_DEPRECATED("use scrollEvent() instead") void mouseScrollEvent(MouseScrollEvent& event); + #endif /** * @brief Multi gesture event @@ -1327,6 +1345,7 @@ class Sdl2Application { /* Calls the base pointer*Event() in order to delegate to deprecated mouse events */ template friend class BasicScreenedApplication; + template friend struct Implementation::ApplicationScrollEventMixin; #endif enum class Flag: UnsignedByte; @@ -2259,10 +2278,9 @@ class Sdl2Application::ViewportEvent { /** @brief Base for input events -@see @ref KeyEvent, @ref PointerEvent, @ref PointerMoveEvent, - @ref MouseScrollEvent, @ref keyPressEvent(), @ref keyReleaseEvent(), - @ref pointerPressEvent(), @ref pointerReleaseEvent(), - @ref pointerMoveEvent(), @ref mouseScrollEvent() +@see @ref KeyEvent, @ref PointerEvent, @ref PointerMoveEvent, @ref ScrollEvent, + @ref keyPressEvent(), @ref keyReleaseEvent(), @ref pointerPressEvent(), + @ref pointerReleaseEvent(), @ref pointerMoveEvent(), @ref scrollEvent() */ class Sdl2Application::InputEvent { public: @@ -2272,7 +2290,7 @@ class Sdl2Application::InputEvent { * @see @ref Modifiers, @ref KeyEvent::modifiers(), * @ref PointerEvent::modifiers(), * @ref PointerMoveEvent::modifiers(), - * @ref MouseScrollEvent::modifiers() + * @ref ScrollEvent::modifiers() */ enum class Modifier: Uint16 { /** @@ -2331,7 +2349,7 @@ class Sdl2Application::InputEvent { * * @see @ref KeyEvent::modifiers(), @ref PointerEvent::modifiers(), * @ref PointerMoveEvent::modifiers(), - * @ref MouseScrollEvent::modifiers() + * @ref ScrollEvent::modifiers() */ typedef Containers::EnumSet Modifiers; @@ -2366,7 +2384,7 @@ class Sdl2Application::InputEvent { * Of type `SDL_KEYDOWN` / `SDL_KEYUP` for @ref KeyEvent, * `SDL_MOUSEBUTTONDOWN` / `SDL_MOUSEBUTTONUP` for @ref PointerEvent, * `SDL_MOUSEMOTION` for @ref PointerMoveEvent and `SDL_MOUSEWHEEL` for - * @ref MouseScrollEvent. + * @ref ScrollEvent. * @see @ref Sdl2Application::anyEvent() */ const SDL_Event& event() const { return _event; } @@ -2990,12 +3008,51 @@ CORRADE_ENUMSET_OPERATORS(Sdl2Application::MouseMoveEvent::Buttons) CORRADE_IGNORE_DEPRECATED_POP #endif +/** +@brief Scroll event +@m_since_latest + +@see @ref PointerEvent, @ref PointerMoveEvent, @ref scrollEvent() +*/ +class Sdl2Application::ScrollEvent: public Sdl2Application::InputEvent { + public: + /** @brief Scroll offset */ + Vector2 offset() const { return _offset; } + + /** + * @brief Position + * + * For mouse input the position is always reported in whole pixels. + * Lazily populated on first request. + */ + Vector2 position(); + + /** + * @brief Modifiers + * + * Lazily populated on first request. + */ + Modifiers modifiers(); + + private: + friend Sdl2Application; + + explicit ScrollEvent(const SDL_Event& event, const Vector2& offset): InputEvent{event}, _offset{offset} {} + + const Vector2 _offset; + Containers::Optional _position; + Containers::Optional _modifiers; +}; + +#ifdef MAGNUM_BUILD_DEPRECATED /** @brief Mouse scroll event +@m_deprecated_since_latest Use @ref ScrollEvent and @ref scrollEvent() instead, + which isn't semantically tied to just a mouse. -@see @ref PointerEvent, @ref PointerMoveEvent, @ref mouseScrollEvent() +@see @ref MouseEvent, @ref MouseMoveEvent, @ref mouseScrollEvent() */ -class Sdl2Application::MouseScrollEvent: public Sdl2Application::InputEvent { +class CORRADE_DEPRECATED("use ScrollEvent and scrollEvent() instead") Sdl2Application::MouseScrollEvent: public InputEvent { public: /** @brief Scroll offset */ Vector2 offset() const { return _offset; } @@ -3023,6 +3080,7 @@ class Sdl2Application::MouseScrollEvent: public Sdl2Application::InputEvent { Containers::Optional _position; Containers::Optional _modifiers; }; +#endif /** @brief Multi gesture event diff --git a/src/Magnum/Platform/Test/AbstractXApplicationTest.cpp b/src/Magnum/Platform/Test/AbstractXApplicationTest.cpp index 00eefcd3f..de6d777d1 100644 --- a/src/Magnum/Platform/Test/AbstractXApplicationTest.cpp +++ b/src/Magnum/Platform/Test/AbstractXApplicationTest.cpp @@ -299,8 +299,8 @@ struct AbstractXApplicationTest: Platform::Application { /* Comment out to test the deprecated scroll as press/release reporting */ #if 1 - void mouseScrollEvent(MouseScrollEvent& event) override { - Debug{} << "mouse scroll:" << event.pointers() << event.modifiers() << Debug::packed << event.offset() << Debug::packed << event.position(); + void scrollEvent(ScrollEvent& event) override { + Debug{} << "scroll:" << event.pointers() << event.modifiers() << Debug::packed << event.offset() << Debug::packed << event.position(); } #endif diff --git a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp index b0bfb9ce2..8b8f12ad9 100644 --- a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp +++ b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp @@ -299,6 +299,9 @@ struct EmscriptenApplicationTest: Platform::Application { void pointerMoveEvent(PointerMoveEvent& event) override { Debug{} << "pointer move:" << event.pointer() << event.pointers() << event.modifiers() << Debug::packed << event.position() << Debug::packed << event.relativePosition(); } + void scrollEvent(ScrollEvent& event) override { + Debug{} << "scroll:" << event.modifiers() << Debug::packed << event.offset() << Debug::packed << event.position(); + } #else CORRADE_IGNORE_DEPRECATED_PUSH void mousePressEvent(MouseEvent& event) override { @@ -310,12 +313,11 @@ struct EmscriptenApplicationTest: Platform::Application { void mouseMoveEvent(MouseMoveEvent& event) override { Debug{} << "mouse move:" << event.buttons() << event.modifiers() << Debug::packed << event.position() << Debug::packed << event.relativePosition(); } - CORRADE_IGNORE_DEPRECATED_POP - #endif - void mouseScrollEvent(MouseScrollEvent& event) override { Debug{} << "mouse scroll:" << event.modifiers() << Debug::packed << event.offset() << Debug::packed << event.position(); } + CORRADE_IGNORE_DEPRECATED_POP + #endif /* For testing keyboard capture */ void keyPressEvent(KeyEvent& event) override { diff --git a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp index 5b2f4c52f..7ba653a9f 100644 --- a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp +++ b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp @@ -363,6 +363,9 @@ struct GlfwApplicationTest: Platform::Application { void pointerMoveEvent(PointerMoveEvent& event) override { Debug{} << "pointer move:" << event.pointer() << event.pointers() << event.modifiers() << Debug::packed << event.position() << Debug::packed << event.relativePosition(); } + void scrollEvent(ScrollEvent& event) override { + Debug{} << "scroll:" << event.modifiers() << Debug::packed << event.offset() << Debug::packed << event.position(); + } #else CORRADE_IGNORE_DEPRECATED_PUSH void mousePressEvent(MouseEvent& event) override { @@ -374,12 +377,11 @@ struct GlfwApplicationTest: Platform::Application { void mouseMoveEvent(MouseMoveEvent& event) override { Debug{} << "mouse move:" << event.buttons() << event.modifiers() << Debug::packed << event.position() << Debug::packed << event.relativePosition(); } - CORRADE_IGNORE_DEPRECATED_POP - #endif - void mouseScrollEvent(MouseScrollEvent& event) override { Debug{} << "mouse scroll:" << event.modifiers() << Debug::packed << event.offset() << Debug::packed << event.position(); } + CORRADE_IGNORE_DEPRECATED_POP + #endif void textInputEvent(TextInputEvent& event) override { Debug{} << "text input:" << event.text(); diff --git a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp index ee5627b28..1dccaf7ae 100644 --- a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp +++ b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp @@ -334,6 +334,9 @@ struct Sdl2ApplicationTest: Platform::Application { void pointerMoveEvent(PointerMoveEvent& event) override { Debug{} << "pointer move:" << event.pointer() << event.pointers() << event.modifiers() << Debug::packed << event.position() << Debug::packed << event.relativePosition(); } + void scrollEvent(ScrollEvent& event) override { + Debug{} << "scroll:" << event.modifiers() << Debug::packed << event.offset() << Debug::packed << event.position(); + } #else CORRADE_IGNORE_DEPRECATED_PUSH void mousePressEvent(MouseEvent& event) override { @@ -349,12 +352,11 @@ struct Sdl2ApplicationTest: Platform::Application { void mouseMoveEvent(MouseMoveEvent& event) override { Debug{} << "mouse move:" << event.buttons() << Debug::packed << event.position() << Debug::packed << event.relativePosition() << event.modifiers(); } - CORRADE_IGNORE_DEPRECATED_POP - #endif - void mouseScrollEvent(MouseScrollEvent& event) override { Debug{} << "mouse scroll:" << event.modifiers() << Debug::packed << event.offset() << Debug::packed << event.position(); } + CORRADE_IGNORE_DEPRECATED_POP + #endif void multiGestureEvent(MultiGestureEvent& event) override { Debug{} << "multi gesture:" << event.center() << "rotation:" << Deg{_gestureRotation} << Debug::nospace << ", relative" << Deg{event.relativeRotation()} << Debug::nospace << ", distance" << _gestureDistance << Debug::nospace << ", relative" << event.relativeDistance() << Debug::nospace << ", fingers" << event.fingerCount();