Browse Source

Platform: replace mouse events with pointer events in GlfwApplication.

For the most part is the same as in Sdl2Application, except that here
GLFW already returned floating-point coordinates, which this finally
makes use of.
pull/651/head
Vladimír Vondruš 2 years ago
parent
commit
5110b40b16
  1. 3
      doc/changelog.dox
  2. 202
      src/Magnum/Platform/GlfwApplication.cpp
  3. 316
      src/Magnum/Platform/GlfwApplication.h
  4. 63
      src/Magnum/Platform/Test/GlfwApplicationTest.cpp

3
doc/changelog.dox

@ -1394,7 +1394,8 @@ See also:
@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
a better abstraction over general pointer input, not just a mouse alone.
The same change is done in @ref Platform::GlfwApplication.
- @cpp Shaders::DistanceFieldVector @ce, @cpp Shaders::Flat @ce,
@cpp Shaders::Generic @ce, @cpp Shaders::MeshVisualizer2D @ce,
@cpp Shaders::MeshVisualizer3D @ce, @cpp Shaders::Phong @ce,

202
src/Magnum/Platform/GlfwApplication.cpp

@ -606,6 +606,52 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf
}
#endif
namespace {
GlfwApplication::Pointer buttonToPointer(const int button) {
switch(button) {
case GLFW_MOUSE_BUTTON_LEFT:
return GlfwApplication::Pointer::MouseLeft;
case GLFW_MOUSE_BUTTON_MIDDLE:
return GlfwApplication::Pointer::MouseMiddle;
case GLFW_MOUSE_BUTTON_RIGHT:
return GlfwApplication::Pointer::MouseRight;
case GLFW_MOUSE_BUTTON_4:
return GlfwApplication::Pointer::MouseButton4;
case GLFW_MOUSE_BUTTON_5:
return GlfwApplication::Pointer::MouseButton5;
case GLFW_MOUSE_BUTTON_6:
return GlfwApplication::Pointer::MouseButton6;
case GLFW_MOUSE_BUTTON_7:
return GlfwApplication::Pointer::MouseButton7;
case GLFW_MOUSE_BUTTON_8:
return GlfwApplication::Pointer::MouseButton8;
}
CORRADE_INTERNAL_ASSERT_UNREACHABLE();
}
GlfwApplication::Pointers currentGlfwPointers(GLFWwindow* const window) {
GlfwApplication::Pointers pointers;
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
pointers |= GlfwApplication::Pointer::MouseLeft;
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS)
pointers |= GlfwApplication::Pointer::MouseMiddle;
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS)
pointers |= GlfwApplication::Pointer::MouseRight;
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_4) == GLFW_PRESS)
pointers |= GlfwApplication::Pointer::MouseButton4;
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_5) == GLFW_PRESS)
pointers |= GlfwApplication::Pointer::MouseButton5;
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_6) == GLFW_PRESS)
pointers |= GlfwApplication::Pointer::MouseButton6;
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_7) == GLFW_PRESS)
pointers |= GlfwApplication::Pointer::MouseButton7;
return pointers;
}
}
void GlfwApplication::setupCallbacks() {
glfwSetWindowUserPointer(_window, this);
glfwSetWindowCloseCallback(_window, [](GLFWwindow* const window){
@ -644,25 +690,41 @@ void GlfwApplication::setupCallbacks() {
glfwSetMouseButtonCallback(_window, [](GLFWwindow* const window, const int button, const int action, const int mods) {
auto& app = *static_cast<GlfwApplication*>(glfwGetWindowUserPointer(window));
const Pointer pointer = buttonToPointer(button);
double x, y;
glfwGetCursorPos(window, &x, &y);
MouseEvent e(static_cast<MouseEvent::Button>(button), {Int(x), Int(y)}, {static_cast<InputEvent::Modifier>(mods)});
if(action == GLFW_PRESS) /* we don't handle GLFW_REPEAT */
app.mousePressEvent(e);
else if(action == GLFW_RELEASE)
app.mouseReleaseEvent(e);
const Vector2 position{Float(x), Float(y)};
/* If an additional mouse button was pressed or some buttons are still
left pressed after a release, call a move event instead */
const Pointers pointers = currentGlfwPointers(window);
if((action == GLFW_PRESS && (pointers & ~pointer)) ||
(action == GLFW_RELEASE && pointers)) {
PointerMoveEvent e{window, pointer, position, {}};
/* We had to query the pointers already and get the modifiers in
the callback, set them directly instead of having them lazily
populated later */
e._pointers = pointers;
e._modifiers = InputEvent::Modifiers{mods};
app.pointerMoveEvent(e);
} else {
PointerEvent e{pointer, position, InputEvent::Modifiers{mods}};
if(action == GLFW_PRESS) /* we don't handle GLFW_REPEAT */
app.pointerPressEvent(e);
else if(action == GLFW_RELEASE)
app.pointerReleaseEvent(e);
}
});
glfwSetCursorPosCallback(_window, [](GLFWwindow* const window, const double x, const double y) {
auto& app = *static_cast<GlfwApplication*>(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{} :
const Vector2 position{Float(x), Float(y)};
PointerMoveEvent e{window, {}, position,
Math::isNan(app._previousMouseMovePosition).all() ? Vector2{} :
position - app._previousMouseMovePosition};
app._previousMouseMovePosition = position;
app.mouseMoveEvent(e);
app.pointerMoveEvent(e);
});
glfwSetScrollCallback(_window, [](GLFWwindow* window, double xoffset, double yoffset) {
MouseScrollEvent e(window, Vector2{Float(xoffset), Float(yoffset)});
@ -903,9 +965,113 @@ void GlfwApplication::tickEvent() {
void GlfwApplication::viewportEvent(ViewportEvent&) {}
void GlfwApplication::keyPressEvent(KeyEvent&) {}
void GlfwApplication::keyReleaseEvent(KeyEvent&) {}
#ifdef MAGNUM_BUILD_DEPRECATED
namespace {
CORRADE_IGNORE_DEPRECATED_PUSH
GlfwApplication::MouseEvent::Button pointerToButton(const GlfwApplication::Pointer pointer) {
switch(pointer) {
case GlfwApplication::Pointer::MouseLeft:
return GlfwApplication::MouseEvent::Button::Left;
case GlfwApplication::Pointer::MouseMiddle:
return GlfwApplication::MouseEvent::Button::Middle;
case GlfwApplication::Pointer::MouseRight:
return GlfwApplication::MouseEvent::Button::Right;
case GlfwApplication::Pointer::MouseButton4:
return GlfwApplication::MouseEvent::Button::Button4;
case GlfwApplication::Pointer::MouseButton5:
return GlfwApplication::MouseEvent::Button::Button5;
case GlfwApplication::Pointer::MouseButton6:
return GlfwApplication::MouseEvent::Button::Button6;
case GlfwApplication::Pointer::MouseButton7:
return GlfwApplication::MouseEvent::Button::Button7;
case GlfwApplication::Pointer::MouseButton8:
return GlfwApplication::MouseEvent::Button::Button8;
}
CORRADE_INTERNAL_ASSERT_UNREACHABLE();
}
CORRADE_IGNORE_DEPRECATED_POP
}
#endif
void GlfwApplication::pointerPressEvent(PointerEvent& event) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
MouseEvent mouseEvent{pointerToButton(event.pointer()), Vector2i{Math::round(event.position())}, event.modifiers()};
mousePressEvent(mouseEvent);
CORRADE_IGNORE_DEPRECATED_POP
#else
static_cast<void>(event);
#endif
}
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
void GlfwApplication::mousePressEvent(MouseEvent&) {}
CORRADE_IGNORE_DEPRECATED_POP
#endif
void GlfwApplication::pointerReleaseEvent(PointerEvent& event) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
MouseEvent mouseEvent{pointerToButton(event.pointer()), Vector2i{Math::round(event.position())}, event.modifiers()};
mouseReleaseEvent(mouseEvent);
CORRADE_IGNORE_DEPRECATED_POP
#else
static_cast<void>(event);
#endif
}
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
void GlfwApplication::mouseReleaseEvent(MouseEvent&) {}
CORRADE_IGNORE_DEPRECATED_POP
#endif
void GlfwApplication::pointerMoveEvent(PointerMoveEvent& event) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
const Vector2i roundedPosition{Math::round(event.position())};
/* If the event is due to some button being additionally pressed or one
button from a larger set being released, delegate to a press/release
event instead */
if(event.pointer()) {
/* GLFW reports either a move or a press/release, so there shouldn't be
any move in this case */
CORRADE_INTERNAL_ASSERT(event.relativePosition() == Vector2{});
MouseEvent mouseEvent{pointerToButton(*event.pointer()),
roundedPosition, event.modifiers()};
event.pointers() >= *event.pointer() ?
mousePressEvent(mouseEvent) : mouseReleaseEvent(mouseEvent);
} else {
/* Can't do just Math::round(event.relativePosition()) because if the
previous position was 4.6 and the new 5.3, they both round to 5 but
the relativePosition is 0.6 and rounds to 1. Conversely, if it'd be
5.3 and 5.6, the positions round to 5 and 6 but relative position
stays 0. */
const Vector2i previousRoundedPosition{Math::round(event.position() - event.relativePosition())};
/* Call the event only if the integer values actually changed */
if(roundedPosition != previousRoundedPosition) {
MouseMoveEvent mouseEvent{_window, roundedPosition, roundedPosition - previousRoundedPosition};
mouseMoveEvent(mouseEvent);
}
}
CORRADE_IGNORE_DEPRECATED_POP
#else
static_cast<void>(event);
#endif
}
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
void GlfwApplication::mouseMoveEvent(MouseMoveEvent&) {}
CORRADE_IGNORE_DEPRECATED_POP
#endif
void GlfwApplication::mouseScrollEvent(MouseScrollEvent&) {}
void GlfwApplication::textInputEvent(TextInputEvent&) {}
@ -952,6 +1118,20 @@ Containers::StringView GlfwApplication::KeyEvent::keyName() const {
}
#endif
GlfwApplication::Pointers GlfwApplication::PointerMoveEvent::pointers() {
if(!_pointers)
_pointers = currentGlfwPointers(_window);
return *_pointers;
}
auto GlfwApplication::PointerMoveEvent::modifiers() -> Modifiers {
if(!_modifiers) _modifiers = currentGlfwModifiers(_window);
return *_modifiers;
}
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
auto GlfwApplication::MouseMoveEvent::buttons() -> Buttons {
if(!_buttons) {
_buttons = Buttons{};
@ -970,6 +1150,8 @@ auto GlfwApplication::MouseMoveEvent::modifiers() -> Modifiers {
if(!_modifiers) _modifiers = currentGlfwModifiers(_window);
return *_modifiers;
}
CORRADE_IGNORE_DEPRECATED_POP
#endif
Vector2i GlfwApplication::MouseScrollEvent::position() {
if(!_position) {

316
src/Magnum/Platform/GlfwApplication.h

@ -178,11 +178,28 @@ class GlfwApplication {
class ViewportEvent;
class InputEvent;
class KeyEvent;
class PointerEvent;
class PointerMoveEvent;
#ifdef MAGNUM_BUILD_DEPRECATED
class MouseEvent;
class MouseMoveEvent;
#endif
class MouseScrollEvent;
class TextInputEvent;
/* The damn thing cannot handle forward enum declarations */
#ifndef DOXYGEN_GENERATING_OUTPUT
enum class Pointer: UnsignedByte;
#endif
/**
* @brief Set of pointer types
* @m_since_latest
*
* @see @ref PointerMoveEvent::pointers()
*/
typedef Containers::EnumSet<Pointer> Pointers;
#ifdef MAGNUM_TARGET_GL
/**
* @brief Construct with an OpenGL context
@ -596,7 +613,7 @@ class GlfwApplication {
* @}
*/
/** @{ @name Mouse handling */
/** @{ @name Pointer handling */
public:
/**
@ -674,19 +691,90 @@ class GlfwApplication {
}
private:
/** @copydoc Sdl2Application::mousePressEvent() */
virtual void mousePressEvent(MouseEvent& event);
/**
* @brief Pointer press event
* @m_since_latest
*
* Called when a mouse is pressed. Note that if at least one mouse
* button is already pressed and another button gets pressed in
* addition, @ref pointerMoveEvent() with the new combination is
* called, not this function.
*
* On builds with @ref MAGNUM_BUILD_DEPRECATED enabled, default
* implementation delegates to @ref mousePressEvent(). On builds with
* deprecated functionality disabled, default implementation does
* nothing.
*/
virtual void pointerPressEvent(PointerEvent& event);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Mouse press event
* @m_deprecated_since_latest Use @ref pointerPressEvent() instead,
* which is a better abstraction for covering both mouse and touch
* / pen input.
*
* Default implementation does nothing.
*/
virtual CORRADE_DEPRECATED("use pointerPressEvent() instead") void mousePressEvent(MouseEvent& event);
#endif
/**
* @brief Pointer release event
* @m_since_latest
*
* Called when a mouse is released. Note that if multiple mouse buttons
* are pressed and one of these is released, @ref pointerMoveEvent()
* with the new combination is called, not this function.
*
* On builds with @ref MAGNUM_BUILD_DEPRECATED enabled, default
* implementation delegates to @ref mouseReleaseEvent(). On builds with
* deprecated functionality disabled, default implementation does
* nothing.
*/
virtual void pointerReleaseEvent(PointerEvent& event);
/** @copydoc Sdl2Application::mouseReleaseEvent() */
virtual void mouseReleaseEvent(MouseEvent& event);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Mouse release event
* @m_deprecated_since_latest Use @ref pointerReleaseEvent() instead,
* which is a better abstraction for covering both mouse and touch
* / pen input.
*
* Default implementation does nothing.
*/
virtual CORRADE_DEPRECATED("use pointerReleaseEvent() instead") void mouseReleaseEvent(MouseEvent& event);
#endif
/**
* @brief Pointer move event
* @m_since_latest
*
* Called when any of the currently pressed pointers is moved or
* changes its properties. Gets called also if the set of pressed mouse
* buttons changes.
*
* On builds with @ref MAGNUM_BUILD_DEPRECATED enabled, default
* implementation delegates to @ref mouseMoveEvent(), or if
* @ref PointerMoveEvent::pointer() is not
* @relativeref{Corrade,Containers::NullOpt}, to either
* @ref mousePressEvent() or @ref mouseReleaseEvent(). On builds with
* deprecated functionality disabled, default implementation does
* nothing.
*/
virtual void pointerMoveEvent(PointerMoveEvent& event);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Mouse move event
* @m_deprecated_since_latest Use @ref pointerMoveEvent() instead,
* which is a better abstraction for covering both mouse and touch
* / pen input.
*
* Called when any mouse button is pressed and mouse is moved. Default
* implementation does nothing.
* Default implementation does nothing.
*/
virtual void mouseMoveEvent(MouseMoveEvent& event);
virtual CORRADE_DEPRECATED("use pointerMoveEvent() instead") void mouseMoveEvent(MouseMoveEvent& event);
#endif
/** @copydoc Sdl2Application::mouseScrollEvent() */
virtual void mouseScrollEvent(MouseScrollEvent& event);
@ -816,9 +904,59 @@ class GlfwApplication {
int _exitCode = 0;
Vector2i _minWindowSize, _maxWindowSize;
Vector2i _previousMouseMovePosition{-1};
Vector2 _previousMouseMovePosition{Constants::nan()};
};
/**
@brief Pointer type
@m_since_latest
@see @ref Pointers, @ref PointerEvent::pointer(),
@ref PointerMoveEvent::pointer(), @ref PointerMoveEvent::pointers()
*/
enum class GlfwApplication::Pointer: UnsignedByte {
/**
* Left mouse button. Corresponds to `GLFW_MOUSE_BUTTON_LEFT` or
* `GLFW_MOUSE_BUTTON_1`.
*/
MouseLeft = 1 << 0,
/**
* Middle mouse button. Corresponds to `GLFW_MOUSE_BUTTON_MIDDLE` or
* `GLFW_MOUSE_BUTTON_2`.
*/
MouseMiddle = 1 << 1,
/**
* Right mouse button. Corresponds to `GLFW_MOUSE_BUTTON_RIGHT` or
* `GLFW_MOUSE_BUTTON_3`.
*/
MouseRight = 1 << 2,
/**
* Fourth mouse button, such as wheel left. Corresponds to
* `GLFW_MOUSE_BUTTON_4`.
*/
MouseButton4 = 1 << 3,
/**
* Fifth mouse button, such as wheel right. Corresponds to
* `GLFW_MOUSE_BUTTON_5`.
*/
MouseButton5 = 1 << 4,
/** Sixth mouse button. Corresponds to `GLFW_MOUSE_BUTTON_6`. */
MouseButton6 = 1 << 5,
/** Seventh mouse button. Corresponds to `GLFW_MOUSE_BUTTON_7`. */
MouseButton7 = 1 << 6,
/** Eighth mouse button. Corresponds to `GLFW_MOUSE_BUTTON_8`. */
MouseButton8 = 1 << 7
};
CORRADE_ENUMSET_OPERATORS(GlfwApplication::Pointers)
#ifdef MAGNUM_TARGET_GL
/**
@brief OpenGL context configuration
@ -1552,8 +1690,10 @@ class GlfwApplication::ViewportEvent {
/**
@brief Base for input events
@see @ref KeyEvent, @ref MouseEvent, @ref MouseMoveEvent, @ref keyPressEvent(),
@ref mousePressEvent(), @ref mouseReleaseEvent(), @ref mouseMoveEvent()
@see @ref KeyEvent, @ref PointerEvent, @ref PointerMoveEvent,
@ref MouseScrollEvent, @ref keyPressEvent(), @ref keyReleaseEvent(),
@ref pointerPressEvent(), @ref pointerReleaseEvent(),
@ref pointerMoveEvent(), @ref mouseScrollEvent()
*/
class GlfwApplication::InputEvent {
public:
@ -1561,7 +1701,9 @@ class GlfwApplication::InputEvent {
* @brief Modifier
*
* @see @ref Modifiers, @ref KeyEvent::modifiers(),
* @ref MouseEvent::modifiers()
* @ref PointerEvent::modifiers(),
* @ref PointerMoveEvent::modifiers(),
* @ref MouseScrollEvent::modifiers()
*/
enum class Modifier: Int {
/**
@ -1596,8 +1738,9 @@ class GlfwApplication::InputEvent {
/**
* @brief Set of modifiers
*
* @see @ref KeyEvent::modifiers(), @ref MouseEvent::modifiers(),
* @ref MouseMoveEvent::modifiers()
* @see @ref KeyEvent::modifiers(), @ref PointerEvent::modifiers(),
* @ref PointerMoveEvent::modifiers(),
* @ref MouseScrollEvent::modifiers()
*/
typedef Containers::EnumSet<Modifier> Modifiers;
@ -1939,13 +2082,63 @@ class GlfwApplication::KeyEvent: public GlfwApplication::InputEvent {
const bool _repeated;
};
/**
@brief Pointer event
@m_since_latest
@see @ref PointerMoveEvent, @ref MouseScrollEvent, @ref pointerPressEvent(),
@ref pointerReleaseEvent()
*/
class GlfwApplication::PointerEvent: public InputEvent {
public:
/** @brief Copying is not allowed */
PointerEvent(const PointerEvent&) = delete;
/** @brief Moving is not allowed */
PointerEvent(PointerEvent&&) = delete;
/** @brief Copying is not allowed */
PointerEvent& operator=(const PointerEvent&) = delete;
/** @brief Moving is not allowed */
PointerEvent& operator=(PointerEvent&&) = delete;
/** @brief Pointer type that was pressed or released */
Pointer pointer() const { return _pointer; }
/**
* @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.
*/
Vector2 position() const { return _position; }
/** @brief Modifiers */
Modifiers modifiers() const { return _modifiers; }
private:
friend GlfwApplication;
explicit PointerEvent(Pointer pointer, const Vector2& position, Modifiers modifiers): _pointer(pointer), _position{position}, _modifiers{modifiers} {}
const Pointer _pointer;
const Vector2 _position;
const Modifiers _modifiers;
};
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@brief Mouse event
@m_deprecated_since_latest Use @ref PointerEvent, @ref pointerPressEvent() and
@ref pointerReleaseEvent() instead, which is a better abstraction for
covering both mouse and touch input.
@see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(),
@ref mouseReleaseEvent()
*/
class GlfwApplication::MouseEvent: public GlfwApplication::InputEvent {
class CORRADE_DEPRECATED("use PointerEvent, pointerPressEvent() and pointerReleaseEvent() instead") GlfwApplication::MouseEvent: public InputEvent {
public:
/**
* @brief Mouse button
@ -1984,13 +2177,99 @@ class GlfwApplication::MouseEvent: public GlfwApplication::InputEvent {
const Vector2i _position;
const Modifiers _modifiers;
};
#endif
/**
@brief Pointer move event
@m_since_latest
@see @ref PointerEvent, @ref MouseScrollEvent, @ref pointerMoveEvent()
*/
class GlfwApplication::PointerMoveEvent: public InputEvent {
public:
/** @brief Copying is not allowed */
PointerMoveEvent(const PointerMoveEvent&) = delete;
/** @brief Moving is not allowed */
PointerMoveEvent(PointerMoveEvent&&) = delete;
/** @brief Copying is not allowed */
PointerMoveEvent& operator=(const PointerMoveEvent&) = delete;
/** @brief Moving is not allowed */
PointerMoveEvent& operator=(PointerMoveEvent&&) = delete;
/**
* @brief Pointer type that was added or removed from the set of pressed pointers
*
* Is non-empty only in case a mouse button was pressed in addition to
* an already pressed button, or if one mouse button from multiple
* pressed buttons was released. If non-empty and @ref pointers() don't
* contain given @ref Pointer value, the button was released, if they
* contain given value, the button was pressed.
*/
Containers::Optional<Pointer> pointer() const { return _pointer; }
/**
* @brief Pointer types pressed in this event
*
* Returns an empty set if no pointers are pressed, which happens for
* example when a mouse is just moved around. Lazily populated on first
* request.
* @see @ref pointer()
*/
Pointers pointers();
/**
* @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.
*/
Vector2 position() const { return _position; }
/**
* @brief Position relative to the previous touch event
*
* 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. Unlike
* @ref Sdl2Application, GLFW doesn't provide relative position
* directly, so this is calculated explicitly as a delta from previous
* move event position.
*/
Vector2 relativePosition() const { return _relativePosition; }
/**
* @brief Modifiers
*
* Lazily populated on first request.
*/
Modifiers modifiers();
private:
friend GlfwApplication;
explicit PointerMoveEvent(GLFWwindow* window, Containers::Optional<Pointer> pointer, const Vector2& position, const Vector2& relativePosition): _window{window}, _pointer{pointer}, _position{position}, _relativePosition{relativePosition} {}
GLFWwindow* const _window;
const Containers::Optional<Pointer> _pointer;
Containers::Optional<Pointers> _pointers;
const Vector2 _position, _relativePosition;
Containers::Optional<Modifiers> _modifiers;
};
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@brief Mouse move event
@m_deprecated_since_latest Use @ref PointerMoveEvent and
@ref pointerMoveEvent() instead, which is a better abstraction for covering
both mouse and touch / pen input.
@see @ref MouseEvent, @ref MouseScrollEvent, @ref mouseMoveEvent()
*/
class GlfwApplication::MouseMoveEvent: public GlfwApplication::InputEvent {
class CORRADE_DEPRECATED("use PointerMoveEvent and pointerMoveEvent() instead") GlfwApplication::MouseMoveEvent: public GlfwApplication::InputEvent {
public:
/**
* @brief Mouse button
@ -2049,12 +2328,15 @@ class GlfwApplication::MouseMoveEvent: public GlfwApplication::InputEvent {
Containers::Optional<Modifiers> _modifiers;
};
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_ENUMSET_OPERATORS(GlfwApplication::MouseMoveEvent::Buttons)
CORRADE_IGNORE_DEPRECATED_POP
#endif
/**
@brief Mouse scroll event
@see @ref MouseEvent, @ref MouseMoveEvent, @ref mouseScrollEvent()
@see @ref PointerEvent, @ref PointerMoveEvent, @ref mouseScrollEvent()
*/
class GlfwApplication::MouseScrollEvent: public GlfwApplication::InputEvent {
public:

63
src/Magnum/Platform/Test/GlfwApplicationTest.cpp

@ -57,7 +57,28 @@ static Debug& operator<<(Debug& debug, Application::InputEvent::Modifier value)
return debug << "(" << Debug::nospace << UnsignedInt(value) << Debug::nospace << ")";
}
static Debug& operator<<(Debug& debug, Application::MouseMoveEvent::Button value) {
static Debug& operator<<(Debug& debug, Application::Pointer value) {
debug << "Pointer" << Debug::nospace;
switch(value) {
#define _c(value) case Application::Pointer::value: return debug << "::" #value;
_c(MouseLeft)
_c(MouseMiddle)
_c(MouseRight)
_c(MouseButton4)
_c(MouseButton5)
_c(MouseButton6)
_c(MouseButton7)
_c(MouseButton8)
#undef _c
}
return debug << "(" << Debug::nospace << UnsignedInt(value) << Debug::nospace << ")";
}
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_UNUSED static Debug& operator<<(Debug& debug, Application::MouseMoveEvent::Button value) {
debug << "Button" << Debug::nospace;
switch(value) {
@ -70,6 +91,8 @@ static Debug& operator<<(Debug& debug, Application::MouseMoveEvent::Button value
return debug << "(" << Debug::nospace << UnsignedInt(value) << Debug::nospace << ")";
}
CORRADE_IGNORE_DEPRECATED_POP
#endif
namespace Test { namespace {
@ -82,7 +105,22 @@ Debug& operator<<(Debug& debug, Application::InputEvent::Modifiers value) {
});
}
Debug& operator<<(Debug& debug, Application::MouseEvent::Button value) {
Debug& operator<<(Debug& debug, Application::Pointers value) {
return Containers::enumSetDebugOutput(debug, value, "Pointers{}", {
Application::Pointer::MouseLeft,
Application::Pointer::MouseMiddle,
Application::Pointer::MouseRight,
Application::Pointer::MouseButton4,
Application::Pointer::MouseButton5,
Application::Pointer::MouseButton6,
Application::Pointer::MouseButton7,
Application::Pointer::MouseButton8,
});
}
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_UNUSED Debug& operator<<(Debug& debug, Application::MouseEvent::Button value) {
debug << "Button" << Debug::nospace;
switch(value) {
@ -101,13 +139,15 @@ Debug& operator<<(Debug& debug, Application::MouseEvent::Button value) {
return debug << "(" << Debug::nospace << UnsignedInt(value) << Debug::nospace << ")";
}
Debug& operator<<(Debug& debug, Application::MouseMoveEvent::Buttons value) {
CORRADE_UNUSED Debug& operator<<(Debug& debug, Application::MouseMoveEvent::Buttons value) {
return Containers::enumSetDebugOutput(debug, value, "Buttons{}", {
Application::MouseMoveEvent::Button::Left,
Application::MouseMoveEvent::Button::Middle,
Application::MouseMoveEvent::Button::Right,
});
}
CORRADE_IGNORE_DEPRECATED_POP
#endif
Debug& operator<<(Debug& debug, const Application::KeyEvent::Key value) {
debug << "Key" << Debug::nospace;
@ -312,17 +352,30 @@ struct GlfwApplicationTest: Platform::Application {
<< event.modifiers();
}
/* Set to 0 to test the deprecated mouse events instead */
#if 1
void pointerPressEvent(PointerEvent& event) override {
Debug{} << "pointer press:" << event.pointer() << event.modifiers() << Debug::packed << event.position();
}
void pointerReleaseEvent(PointerEvent& event) override {
Debug{} << "pointer release:" << event.pointer() << event.modifiers() << Debug::packed << event.position();
}
void pointerMoveEvent(PointerMoveEvent& event) override {
Debug{} << "pointer move:" << event.pointer() << event.pointers() << event.modifiers() << Debug::packed << event.position() << Debug::packed << event.relativePosition();
}
#else
CORRADE_IGNORE_DEPRECATED_PUSH
void mousePressEvent(MouseEvent& event) override {
Debug{} << "mouse press:" << event.button() << event.modifiers() << Debug::packed << event.position();
}
void mouseReleaseEvent(MouseEvent& event) override {
Debug{} << "mouse release:" << event.button() << event.modifiers() << Debug::packed << event.position();
}
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();

Loading…
Cancel
Save