From 89d4a754d53d02d02839b5b44ee3836ae8c9ff7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 9 Aug 2019 22:18:13 +0200 Subject: [PATCH] Platform: add MouseMoveEvent::relativePosition() to Glfw and Emscripten. These toolkits don't support it, but I got really annoyed and so the apps are emulating it. --- doc/changelog.dox | 5 +++++ src/Magnum/Platform/EmscriptenApplication.cpp | 9 ++++++++- src/Magnum/Platform/EmscriptenApplication.h | 15 +++++++++++++-- src/Magnum/Platform/GlfwApplication.cpp | 11 +++++++++-- src/Magnum/Platform/GlfwApplication.h | 18 ++++++++++++++---- src/Magnum/Platform/Sdl2Application.h | 2 +- .../Test/EmscriptenApplicationTest.cpp | 2 +- .../Platform/Test/GlfwApplicationTest.cpp | 4 ++++ .../Platform/Test/Sdl2ApplicationTest.cpp | 2 +- 9 files changed, 56 insertions(+), 12 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index b5bdca4b6..b84f7d88e 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -375,6 +375,11 @@ See also: @ref Platform::GlfwApplication::exit() now have an optional parameter to specify the actual application return code (see [mosra/magnum#332](https://github.com/mosra/magnum/pull/332)) +- @ref Platform::GlfwApplication and @ref Platform::EmscriptenApplication now + implement @ref Platform::GlfwApplication::MouseMoveEvent::relativePosition() + as well for better compatibility with @ref Platform::Sdl2Application. The + relative position is not supplied by the underlying toolkits, so it's + emulated on the application side. - Extended @ref Platform::BasicScreen with @ref Platform::BasicScreen::mouseScrollEvent() "mouseScrollEvent()", @ref Platform::BasicScreen::textInputEvent() "textInputEvent()" and diff --git a/src/Magnum/Platform/EmscriptenApplication.cpp b/src/Magnum/Platform/EmscriptenApplication.cpp index 33f3ab8cc..f37df94c3 100644 --- a/src/Magnum/Platform/EmscriptenApplication.cpp +++ b/src/Magnum/Platform/EmscriptenApplication.cpp @@ -470,7 +470,14 @@ void EmscriptenApplication::setupCallbacks(bool resizable) { emscripten_set_mousemove_callback("#canvas", this, false, ([](int, const EmscriptenMouseEvent* event, void* userData) -> Int { - MouseMoveEvent e{*event}; + auto& app = *static_cast(userData); + /* Avoid bogus offset at first -- report 0 when the event is called + for the first time */ + Vector2i position{Int(event->canvasX), Int(event->canvasY)}; + MouseMoveEvent e{*event, + app._previousMouseMovePosition == Vector2i{-1} ? Vector2i{} : + position - app._previousMouseMovePosition}; + app._previousMouseMovePosition = position; static_cast(userData)->mouseMoveEvent(e); return e.isAccepted(); })); diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index 78ddbf243..9a2bd0f1e 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -639,7 +639,7 @@ class EmscriptenApplication { void setupAnimationFrame(bool ForceAnimationFrame); Vector2 _devicePixelRatio, _dpiScaling; - Vector2i _lastKnownCanvasSize; + Vector2i _lastKnownCanvasSize, _previousMouseMovePosition{-1}; Flags _flags; @@ -1251,6 +1251,16 @@ class EmscriptenApplication::MouseMoveEvent: public EmscriptenApplication::Input /** @brief Position */ Vector2i position() const; + /** + * @brief Relative position + * + * Position relative to previous move event. Unlike + * @ref Sdl2Application, HTML APIs don't provide relative position + * directly, so this is calculated explicitly as a delta from previous + * move event position. + */ + Vector2i relativePosition() const { return _relativePosition; } + /** @brief Mouse buttons */ Buttons buttons() const; @@ -1263,9 +1273,10 @@ class EmscriptenApplication::MouseMoveEvent: public EmscriptenApplication::Input private: friend EmscriptenApplication; - explicit MouseMoveEvent(const EmscriptenMouseEvent& event): _event(event) {} + explicit MouseMoveEvent(const EmscriptenMouseEvent& event, const Vector2i& relativePosition): _event(event), _relativePosition{relativePosition} {} const EmscriptenMouseEvent& _event; + const Vector2i _relativePosition; }; CORRADE_ENUMSET_OPERATORS(EmscriptenApplication::MouseMoveEvent::Buttons) diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 9d38dcf0b..4f4a3ff27 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -517,8 +517,15 @@ void GlfwApplication::setupCallbacks() { app.mouseReleaseEvent(e); }); glfwSetCursorPosCallback(_window, [](GLFWwindow* const window, const double x, const double y) { - MouseMoveEvent e{window, Vector2i{Int(x), Int(y)}}; - static_cast(glfwGetWindowUserPointer(window))->mouseMoveEvent(e); + auto& app = *static_cast(glfwGetWindowUserPointer(window)); + /* Avoid bogus offset at first -- report 0 when the event is called for + the first time */ + Vector2i position{Int(x), Int(y)}; + MouseMoveEvent e{window, position, + app._previousMouseMovePosition == Vector2i{-1} ? Vector2i{} : + position - app._previousMouseMovePosition}; + app._previousMouseMovePosition = position; + app.mouseMoveEvent(e); }); glfwSetScrollCallback(_window, [](GLFWwindow* window, double xoffset, double yoffset) { MouseScrollEvent e(window, Vector2{Float(xoffset), Float(yoffset)}); diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 84c93ccd2..f32f71c39 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -590,8 +590,8 @@ class GlfwApplication { #endif int _exitCode = 0; - Vector2i _minWindowSize; - Vector2i _maxWindowSize; + Vector2i _minWindowSize, _maxWindowSize; + Vector2i _previousMouseMovePosition{-1}; }; #ifdef MAGNUM_TARGET_GL @@ -1590,6 +1590,16 @@ class GlfwApplication::MouseMoveEvent: public GlfwApplication::InputEvent { /** @brief Position */ Vector2i position() const { return _position; } + /** + * @brief Relative position + * + * Position relative to previous move event. Unlike + * @ref Sdl2Application, GLFW doesn't provide relative position + * directly, so this is calculated explicitly as a delta from previous + * move event position. + */ + Vector2i relativePosition() const { return _relativePosition; } + /** * @brief Modifiers * @@ -1600,10 +1610,10 @@ class GlfwApplication::MouseMoveEvent: public GlfwApplication::InputEvent { private: friend GlfwApplication; - explicit MouseMoveEvent(GLFWwindow* window, const Vector2i& position): _window{window}, _position{position} {} + explicit MouseMoveEvent(GLFWwindow* window, const Vector2i& position, const Vector2i& relativePosition): _window{window}, _position{position}, _relativePosition{relativePosition} {} GLFWwindow* const _window; - const Vector2i _position; + const Vector2i _position, _relativePosition; Containers::Optional _buttons; Containers::Optional _modifiers; }; diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 8e1cf78da..5864be4c8 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -2191,7 +2191,7 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent { /** * @brief Relative position * - * Position relative to previous event. + * Position relative to previous move event. */ Vector2i relativePosition() const { return _relativePosition; } diff --git a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp index 737dccaad..f03616de3 100644 --- a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp +++ b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp @@ -80,7 +80,7 @@ struct EmscriptenApplicationTest: Platform::Application { } void mouseMoveEvent(MouseMoveEvent& event) override { - Debug{} << "mouse move event:" << event.position() << Int(event.buttons()); + Debug{} << "mouse move event:" << event.position() << event.relativePosition() << Int(event.buttons()); } void mouseScrollEvent(MouseScrollEvent& event) override { diff --git a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp index c918c22e0..a3b031106 100644 --- a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp +++ b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp @@ -60,6 +60,10 @@ struct GlfwApplicationTest: Platform::Application { } } + void mouseMoveEvent(MouseMoveEvent& event) override { + Debug{} << "mouse move event:" << event.position() << event.relativePosition() << UnsignedInt(event.buttons()); + } + void textInputEvent(TextInputEvent& event) override { Debug{} << "text input event:" << std::string{event.text(), event.text().size()}; } diff --git a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp index bda0ecda4..0574d4b02 100644 --- a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp +++ b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp @@ -63,7 +63,7 @@ struct Sdl2ApplicationTest: Platform::Application { } void mouseMoveEvent(MouseMoveEvent& event) override { - Debug{} << "mouse move event:" << event.position() << Uint32(event.buttons()); + Debug{} << "mouse move event:" << event.position() << event.relativePosition() << Uint32(event.buttons()); } void mouseScrollEvent(MouseScrollEvent& event) override {