Browse Source

Platform: first-class MouseScrollEvent for SDL2 and NaCl application.

The original implementation tried to mimic the behavior of GLUT, which
treats mouse wheel as a button. SDL2, GLFW and NaCl all treat scroll
event separately, so it was quite nastily hacked in, with horizontal
scrolling ignored and scrolling offset treated as cursor position.
Moreover, wheel up/down buttons were confused with extra mouse buttons
in SDL2.

Now there is a dedicated MouseScrollEvent, which has just the offset and
modifiers, no cursor position. The original way with WheelUp/WheelDown
buttons in mouse press event is still preserved, though it is marked as
deprecated and will be removed in future release. Sdl2Application had
WheelUp/WheelDown buttons also for mouse move event, which was
completely useless (try moving a mouse while the wheel is rotating, ha),
so it's removed.

Scroll event offset is now also consistently Vector2 across all toolkits
-- it was integer in SDL2, float in NaCl and double in GLFW.

The X1 and X2 buttons in Sdl2Application are not confused with wheel
up/down anymore and are a new Mouse*Event::Button::X1 and
Mouse*Event::Button::X2 enums -- on my mouse they are actually wheel
left and wheel right (though wheel left and wheel right is not treated
as horizontal scrolling, weird).
pull/158/head
Vladimír Vondruš 10 years ago
parent
commit
2a77856df2
  1. 11
      src/Magnum/Platform/GlfwApplication.cpp
  2. 31
      src/Magnum/Platform/GlfwApplication.h
  3. 14
      src/Magnum/Platform/NaClApplication.cpp
  4. 51
      src/Magnum/Platform/NaClApplication.h
  5. 24
      src/Magnum/Platform/Sdl2Application.cpp
  6. 79
      src/Magnum/Platform/Sdl2Application.h

11
src/Magnum/Platform/GlfwApplication.cpp

@ -187,13 +187,22 @@ void GlfwApplication::staticMouseEvent(GLFWwindow*, int button, int action, int
} }
void GlfwApplication::staticMouseScrollEvent(GLFWwindow* window, double xoffset, double yoffset) { void GlfwApplication::staticMouseScrollEvent(GLFWwindow* window, double xoffset, double yoffset) {
MouseScrollEvent e(Vector2d{xoffset, yoffset}, KeyEvent::getCurrentGlfwModifiers(window)); MouseScrollEvent e(Vector2{Float(xoffset), Float(yoffset)}, KeyEvent::getCurrentGlfwModifiers(window));
_instance->mouseScrollEvent(e); _instance->mouseScrollEvent(e);
#ifdef MAGNUM_BUILD_DEPRECATED
if(yoffset != 0.0) { if(yoffset != 0.0) {
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
MouseEvent e1((yoffset > 0.0) ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, KeyEvent::getCurrentGlfwModifiers(window)); MouseEvent e1((yoffset > 0.0) ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, KeyEvent::getCurrentGlfwModifiers(window));
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
_instance->mousePressEvent(e1); _instance->mousePressEvent(e1);
} }
#endif
} }
void GlfwApplication::staticErrorCallback(int, const char* description) { void GlfwApplication::staticErrorCallback(int, const char* description) {

31
src/Magnum/Platform/GlfwApplication.h

@ -247,12 +247,7 @@ class GlfwApplication {
*/ */
virtual void mouseMoveEvent(MouseMoveEvent& event); virtual void mouseMoveEvent(MouseMoveEvent& event);
/** /** @copydoc Sdl2Application::mouseScrollEvent() */
* @brief Mouse scroll event
*
* Called when a scrolling device is used (mouse wheel or scrolling
* area on touchpad). Default implementation does nothing.
*/
virtual void mouseScrollEvent(MouseScrollEvent& event); virtual void mouseScrollEvent(MouseScrollEvent& event);
/*@}*/ /*@}*/
@ -706,7 +701,8 @@ class GlfwApplication::KeyEvent: public GlfwApplication::InputEvent {
/** /**
@brief Mouse event @brief Mouse event
@see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(), @ref mouseReleaseEvent() @see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(),
@ref mouseReleaseEvent()
*/ */
class GlfwApplication::MouseEvent: public GlfwApplication::InputEvent { class GlfwApplication::MouseEvent: public GlfwApplication::InputEvent {
friend GlfwApplication; friend GlfwApplication;
@ -730,8 +726,19 @@ class GlfwApplication::MouseEvent: public GlfwApplication::InputEvent {
Button7 = GLFW_MOUSE_BUTTON_7, /**< Mouse button 7 */ Button7 = GLFW_MOUSE_BUTTON_7, /**< Mouse button 7 */
Button8 = GLFW_MOUSE_BUTTON_8, /**< Mouse button 8 */ Button8 = GLFW_MOUSE_BUTTON_8, /**< Mouse button 8 */
WheelUp = GLFW_MOUSE_BUTTON_LAST + 1, /**< Mouse wheel up */ #ifdef MAGNUM_BUILD_DEPRECATED
WheelDown = GLFW_MOUSE_BUTTON_LAST + 2 /**< Mouse wheel down */ /**
* Wheel up
* @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead.
*/
WheelUp CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = GLFW_MOUSE_BUTTON_LAST + 1,
/**
* Wheel down
* @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead.
*/
WheelDown CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = GLFW_MOUSE_BUTTON_LAST + 2
#endif
}; };
/** @brief Button */ /** @brief Button */
@ -779,15 +786,15 @@ class GlfwApplication::MouseScrollEvent: public GlfwApplication::InputEvent {
public: public:
/** @brief Scroll offset */ /** @brief Scroll offset */
constexpr Vector2d offset() const { return _offset; } constexpr Vector2 offset() const { return _offset; }
/** @brief Modifiers */ /** @brief Modifiers */
constexpr Modifiers modifiers() const { return _modifiers; } constexpr Modifiers modifiers() const { return _modifiers; }
private: private:
constexpr MouseScrollEvent(const Vector2d& offset, Modifiers modifiers): _offset(offset), _modifiers(modifiers) {} constexpr MouseScrollEvent(const Vector2& offset, Modifiers modifiers): _offset(offset), _modifiers(modifiers) {}
const Vector2d _offset; const Vector2 _offset;
const Modifiers _modifiers; const Modifiers _modifiers;
}; };

14
src/Magnum/Platform/NaClApplication.cpp

@ -192,10 +192,17 @@ bool NaClApplication::HandleInputEvent(const pp::InputEvent& event) {
case PP_INPUTEVENT_TYPE_WHEEL: { case PP_INPUTEVENT_TYPE_WHEEL: {
pp::WheelInputEvent wheelEvent(event); pp::WheelInputEvent wheelEvent(event);
if(Math::TypeTraits<Float>::equals(wheelEvent.GetDelta().y(), 0.0f)) return false; MouseScrollEvent e{{wheelEvent.GetDelta().x(), wheelEvent.GetDelta().y()}, static_cast<InputEvent::Modifier>(wheelEvent.GetModifiers())};
MouseEvent e(wheelEvent.GetDelta().y() > 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {}, static_cast<InputEvent::Modifier>(wheelEvent.GetModifiers())); mouseScrollEvent(e);
mousePressEvent(e); #ifdef MAGNUM_BUILD_DEPRECATED
if(!Math::TypeTraits<Float>::equals(wheelEvent.GetDelta().y(), 0.0f)) {
MouseEvent e2(wheelEvent.GetDelta().y() > 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {}, static_cast<InputEvent::Modifier>(wheelEvent.GetModifiers()));
mousePressEvent(e2);
if(!e.isAccepted() && !e2.isAccepted()) return false;
} else if(!e.isAccepted()) return false;
#else
if(!e.isAccepted()) return false; if(!e.isAccepted()) return false;
#endif
break; break;
} }
@ -261,6 +268,7 @@ void NaClApplication::keyReleaseEvent(KeyEvent&) {}
void NaClApplication::mousePressEvent(MouseEvent&) {} void NaClApplication::mousePressEvent(MouseEvent&) {}
void NaClApplication::mouseReleaseEvent(MouseEvent&) {} void NaClApplication::mouseReleaseEvent(MouseEvent&) {}
void NaClApplication::mouseMoveEvent(MouseMoveEvent&) {} void NaClApplication::mouseMoveEvent(MouseMoveEvent&) {}
void NaClApplication::mouseScrollEvent(MouseScrollEvent&) {}
template class BasicScreen<NaClApplication>; template class BasicScreen<NaClApplication>;
template class BasicScreenedApplication<NaClApplication>; template class BasicScreenedApplication<NaClApplication>;

51
src/Magnum/Platform/NaClApplication.h

@ -204,6 +204,7 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public
class KeyEvent; class KeyEvent;
class MouseEvent; class MouseEvent;
class MouseMoveEvent; class MouseMoveEvent;
class MouseScrollEvent;
/** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -355,6 +356,16 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public
*/ */
virtual void mouseMoveEvent(MouseMoveEvent& event); virtual void mouseMoveEvent(MouseMoveEvent& event);
/**
* @brief Mouse scroll event
*
* Called when a scrolling device is used (mouse wheel or scrolling
* area on a touchpad). Default implementation does nothing. If you
* accept the event, call @ref InputEvent::setAccepted() "setAccepted()"
* on it, otherwise the event will be propagated to the browser.
*/
virtual void mouseScrollEvent(MouseScrollEvent& event);
/*@}*/ /*@}*/
private: private:
@ -650,7 +661,8 @@ class NaClApplication::KeyEvent: public NaClApplication::InputEvent {
@brief Mouse event @brief Mouse event
See also @ref InputEvent for more information. See also @ref InputEvent for more information.
@see @ref MouseMoveEvent, @ref mousePressEvent(), @ref mouseReleaseEvent() @see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(),
@ref mouseReleaseEvent()
*/ */
class NaClApplication::MouseEvent: public NaClApplication::InputEvent { class NaClApplication::MouseEvent: public NaClApplication::InputEvent {
friend NaClApplication; friend NaClApplication;
@ -665,8 +677,20 @@ class NaClApplication::MouseEvent: public NaClApplication::InputEvent {
Left = PP_INPUTEVENT_MOUSEBUTTON_LEFT, /**< Left button */ Left = PP_INPUTEVENT_MOUSEBUTTON_LEFT, /**< Left button */
Middle = PP_INPUTEVENT_MOUSEBUTTON_MIDDLE, /**< Middle button */ Middle = PP_INPUTEVENT_MOUSEBUTTON_MIDDLE, /**< Middle button */
Right = PP_INPUTEVENT_MOUSEBUTTON_RIGHT, /**< Right button */ Right = PP_INPUTEVENT_MOUSEBUTTON_RIGHT, /**< Right button */
WheelUp = 0xFFFF01, /**< Wheel up */
WheelDown = 0xFFFF02 /**< Wheel down */ #ifdef MAGNUM_BUILD_DEPRECATED
/**
* Wheel up
* @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead.
*/
WheelUp CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = 0xFFFF01,
/**
* Wheel down
* @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead.
*/
WheelDown CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = 0xFFFF02
#endif
}; };
/** @brief Button */ /** @brief Button */
@ -692,7 +716,7 @@ class NaClApplication::MouseEvent: public NaClApplication::InputEvent {
@brief Mouse move event @brief Mouse move event
See also @ref InputEvent for more information. See also @ref InputEvent for more information.
@see @ref MouseEvent, @ref mouseMoveEvent() @see @ref MouseEvent, @ref MouseScrollEvent, @ref mouseMoveEvent()
*/ */
class NaClApplication::MouseMoveEvent: public NaClApplication::InputEvent { class NaClApplication::MouseMoveEvent: public NaClApplication::InputEvent {
friend NaClApplication; friend NaClApplication;
@ -714,6 +738,25 @@ class NaClApplication::MouseMoveEvent: public NaClApplication::InputEvent {
const Vector2i _position, _relativePosition; const Vector2i _position, _relativePosition;
}; };
/**
@brief Mouse scroll event
See also @ref InputEvent for more information.
@see @ref MouseEvent, @ref MouseMoveEvent, @ref mouseScrollEvent()
*/
class NaClApplication::MouseScrollEvent: public NaClApplication::InputEvent {
friend NaClApplication;
public:
/** @brief Scroll offset */
constexpr Vector2 offset() const { return _offset; }
private:
constexpr MouseScrollEvent(const Vector2& offset, Modifiers modifiers): InputEvent{modifiers}, _offset{offset} {}
const Vector2 _offset;
};
CORRADE_ENUMSET_OPERATORS(NaClApplication::Flags) CORRADE_ENUMSET_OPERATORS(NaClApplication::Flags)
namespace Implementation { namespace Implementation {

24
src/Magnum/Platform/Sdl2Application.cpp

@ -384,15 +384,28 @@ void Sdl2Application::mainLoop() {
event.type == SDL_MOUSEBUTTONDOWN ? mousePressEvent(e) : mouseReleaseEvent(e); event.type == SDL_MOUSEBUTTONDOWN ? mousePressEvent(e) : mouseReleaseEvent(e);
} break; } break;
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL: {
MouseScrollEvent e{{Float(event.wheel.x), Float(event.wheel.y)}};
mouseScrollEvent(e);
#ifdef MAGNUM_BUILD_DEPRECATED
if(event.wheel.y != 0) { if(event.wheel.y != 0) {
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
MouseEvent e(event.wheel.y > 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {event.wheel.x, event.wheel.y} MouseEvent e(event.wheel.y > 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {event.wheel.x, event.wheel.y}
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
, 0 , 0
#endif #endif
); );
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
mousePressEvent(e); mousePressEvent(e);
} break; }
#endif
} break;
case SDL_MOUSEMOTION: { case SDL_MOUSEMOTION: {
MouseMoveEvent e({event.motion.x, event.motion.y}, {event.motion.xrel, event.motion.yrel}, static_cast<MouseMoveEvent::Button>(event.motion.state)); MouseMoveEvent e({event.motion.x, event.motion.y}, {event.motion.xrel, event.motion.yrel}, static_cast<MouseMoveEvent::Button>(event.motion.state));
@ -510,6 +523,7 @@ void Sdl2Application::keyReleaseEvent(KeyEvent&) {}
void Sdl2Application::mousePressEvent(MouseEvent&) {} void Sdl2Application::mousePressEvent(MouseEvent&) {}
void Sdl2Application::mouseReleaseEvent(MouseEvent&) {} void Sdl2Application::mouseReleaseEvent(MouseEvent&) {}
void Sdl2Application::mouseMoveEvent(MouseMoveEvent&) {} void Sdl2Application::mouseMoveEvent(MouseMoveEvent&) {}
void Sdl2Application::mouseScrollEvent(MouseScrollEvent&) {}
void Sdl2Application::multiGestureEvent(MultiGestureEvent&) {} void Sdl2Application::multiGestureEvent(MultiGestureEvent&) {}
void Sdl2Application::textInputEvent(TextInputEvent&) {} void Sdl2Application::textInputEvent(TextInputEvent&) {}
void Sdl2Application::textEditingEvent(TextEditingEvent&) {} void Sdl2Application::textEditingEvent(TextEditingEvent&) {}
@ -543,6 +557,12 @@ Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseMoveEvent::modifier
return _modifiers = fixedModifiers(Uint16(SDL_GetModState())); return _modifiers = fixedModifiers(Uint16(SDL_GetModState()));
} }
Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseScrollEvent::modifiers() {
if(_modifiersLoaded) return _modifiers;
_modifiersLoaded = true;
return _modifiers = fixedModifiers(Uint16(SDL_GetModState()));
}
template class BasicScreen<Sdl2Application>; template class BasicScreen<Sdl2Application>;
template class BasicScreenedApplication<Sdl2Application>; template class BasicScreenedApplication<Sdl2Application>;

79
src/Magnum/Platform/Sdl2Application.h

@ -331,6 +331,7 @@ class Sdl2Application {
class KeyEvent; class KeyEvent;
class MouseEvent; class MouseEvent;
class MouseMoveEvent; class MouseMoveEvent;
class MouseScrollEvent;
class MultiGestureEvent; class MultiGestureEvent;
class TextInputEvent; class TextInputEvent;
class TextEditingEvent; class TextEditingEvent;
@ -586,6 +587,14 @@ class Sdl2Application {
*/ */
virtual void mouseMoveEvent(MouseMoveEvent& event); virtual void mouseMoveEvent(MouseMoveEvent& event);
/**
* @brief Mouse scroll event
*
* Called when a scrolling device is used (mouse wheel or scrolling
* area on a touchpad). Default implementation does nothing.
*/
virtual void mouseScrollEvent(MouseScrollEvent& event);
/*@}*/ /*@}*/
/** @{ @name Touch gesture handling */ /** @{ @name Touch gesture handling */
@ -1125,7 +1134,8 @@ class Sdl2Application::KeyEvent: public Sdl2Application::InputEvent {
/** /**
@brief Mouse event @brief Mouse event
@see @ref MouseMoveEvent, @ref mousePressEvent(), @ref mouseReleaseEvent() @see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(),
@ref mouseReleaseEvent()
*/ */
class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent { class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent {
friend Sdl2Application; friend Sdl2Application;
@ -1140,26 +1150,38 @@ class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent {
Left = SDL_BUTTON_LEFT, /**< Left button */ Left = SDL_BUTTON_LEFT, /**< Left button */
Middle = SDL_BUTTON_MIDDLE, /**< Middle button */ Middle = SDL_BUTTON_MIDDLE, /**< Middle button */
Right = SDL_BUTTON_RIGHT, /**< Right button */ Right = SDL_BUTTON_RIGHT, /**< Right button */
WheelUp = SDL_BUTTON_X1, /**< Wheel up */
WheelDown = SDL_BUTTON_X2 /**< Wheel down */ /** First extra button (e.g. wheel left) */
X1 = SDL_BUTTON_X1,
/** Second extra button (e.g. wheel right) */
X2 = SDL_BUTTON_X2,
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* Wheel up
* @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead.
*/
WheelUp CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = SDL_BUTTON_X2 + 1,
/**
* Wheel down
* @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead.
*/
WheelDown CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = SDL_BUTTON_X2 + 2
#endif
}; };
/** @brief Button */ /** @brief Button */
constexpr Button button() const { return _button; } constexpr Button button() const { return _button; }
/** /** @brief Position */
* @brief Position
*
* For whell events this contains the horizontal and vertical scroll
* amount.
*/
constexpr Vector2i position() const { return _position; } constexpr Vector2i position() const { return _position; }
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
/** /**
* @brief Click count * @brief Click count
* *
* Ignored for wheel events.
* @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten".
*/ */
constexpr Int clickCount() const { return _clickCount; } constexpr Int clickCount() const { return _clickCount; }
@ -1195,7 +1217,7 @@ class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent {
/** /**
@brief Mouse move event @brief Mouse move event
@see @ref MouseEvent, @ref mouseMoveEvent() @see @ref MouseEvent, @ref MouseScrollEvent, @ref mouseMoveEvent()
*/ */
class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent { class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent {
friend Sdl2Application; friend Sdl2Application;
@ -1210,8 +1232,12 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent {
Left = SDL_BUTTON_LMASK, /**< Left button */ Left = SDL_BUTTON_LMASK, /**< Left button */
Middle = SDL_BUTTON_MMASK, /**< Middle button */ Middle = SDL_BUTTON_MMASK, /**< Middle button */
Right = SDL_BUTTON_RMASK, /**< Right button */ Right = SDL_BUTTON_RMASK, /**< Right button */
WheelUp = SDL_BUTTON_X1MASK, /**< Wheel up */
WheelDown = SDL_BUTTON_X2MASK /**< Wheel down */ /** First extra button (e.g. wheel left) */
X1 = SDL_BUTTON_X1MASK,
/** Second extra button (e.g. wheel right) */
X2 = SDL_BUTTON_X2MASK
}; };
/** /**
@ -1250,6 +1276,33 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent {
Modifiers _modifiers; Modifiers _modifiers;
}; };
/**
@brief Mouse scroll event
@see @ref MouseEvent, @ref MouseMoveEvent, @ref mouseScrollEvent()
*/
class Sdl2Application::MouseScrollEvent: public Sdl2Application::InputEvent {
friend Sdl2Application;
public:
/** @brief Scroll offset */
constexpr Vector2 offset() const { return _offset; }
/**
* @brief Modifiers
*
* Lazily populated on first request.
*/
Modifiers modifiers();
private:
constexpr MouseScrollEvent(const Vector2& offset): _offset{offset}, _modifiersLoaded{false} {}
const Vector2 _offset;
bool _modifiersLoaded;
Modifiers _modifiers;
};
/** /**
@brief Multi gesture event @brief Multi gesture event

Loading…
Cancel
Save