Browse Source

Platform: implement Sdl2Application::anyEvent(), expose SDL_Event.

pull/308/head
Vladimír Vondruš 7 years ago
parent
commit
20a55b16aa
  1. 3
      doc/changelog.dox
  2. 30
      src/Magnum/Platform/Sdl2Application.cpp
  3. 114
      src/Magnum/Platform/Sdl2Application.h
  4. 8
      src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp

3
doc/changelog.dox

@ -91,6 +91,9 @@ See also:
@ref Platform::GlfwApplication::exitEvent() events for responding to @ref Platform::GlfwApplication::exitEvent() events for responding to
application window close and possibility to cancel it (for example to application window close and possibility to cancel it (for example to
show an exit confirmation dialog) show an exit confirmation dialog)
- New @ref Platform::Sdl2Application::anyEvent() event together with
@ref Platform::Sdl2Application::InputEvent::event() "event()" accessors to
make it possible to access raw `SDL_Event` data
@subsection changelog-latest-changes Changes and improvements @subsection changelog-latest-changes Changes and improvements

30
src/Magnum/Platform/Sdl2Application.cpp

@ -665,7 +665,7 @@ void Sdl2Application::mainLoopIteration() {
https://github.com/kripken/emscripten/issues/1731 */ https://github.com/kripken/emscripten/issues/1731 */
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#else #else
ViewportEvent e{{event.window.data1, event.window.data2}, framebufferSize(), _dpiScaling}; ViewportEvent e{event, {event.window.data1, event.window.data2}, framebufferSize(), _dpiScaling};
/** @todo handle also WM_DPICHANGED events when a window is moved between displays with different DPI */ /** @todo handle also WM_DPICHANGED events when a window is moved between displays with different DPI */
viewportEvent(e); viewportEvent(e);
_flags |= Flag::Redraw; _flags |= Flag::Redraw;
@ -678,49 +678,49 @@ void Sdl2Application::mainLoopIteration() {
case SDL_KEYDOWN: case SDL_KEYDOWN:
case SDL_KEYUP: { case SDL_KEYUP: {
KeyEvent e(static_cast<KeyEvent::Key>(event.key.keysym.sym), fixedModifiers(event.key.keysym.mod), event.key.repeat != 0); KeyEvent e{event, static_cast<KeyEvent::Key>(event.key.keysym.sym), fixedModifiers(event.key.keysym.mod), event.key.repeat != 0};
event.type == SDL_KEYDOWN ? keyPressEvent(e) : keyReleaseEvent(e); event.type == SDL_KEYDOWN ? keyPressEvent(e) : keyReleaseEvent(e);
} break; } break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP: { case SDL_MOUSEBUTTONUP: {
MouseEvent e(static_cast<MouseEvent::Button>(event.button.button), {event.button.x, event.button.y} MouseEvent e{event, static_cast<MouseEvent::Button>(event.button.button), {event.button.x, event.button.y}
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
, event.button.clicks , event.button.clicks
#endif #endif
); };
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{event, {Float(event.wheel.x), Float(event.wheel.y)}};
mouseScrollEvent(e); mouseScrollEvent(e);
} break; } 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, {event.motion.x, event.motion.y}, {event.motion.xrel, event.motion.yrel}, static_cast<MouseMoveEvent::Button>(event.motion.state)};
mouseMoveEvent(e); mouseMoveEvent(e);
break; break;
} }
case SDL_MULTIGESTURE: { case SDL_MULTIGESTURE: {
MultiGestureEvent e({event.mgesture.x, event.mgesture.y}, event.mgesture.dTheta, event.mgesture.dDist, event.mgesture.numFingers); MultiGestureEvent e{event, {event.mgesture.x, event.mgesture.y}, event.mgesture.dTheta, event.mgesture.dDist, event.mgesture.numFingers};
multiGestureEvent(e); multiGestureEvent(e);
break; break;
} }
case SDL_TEXTINPUT: { case SDL_TEXTINPUT: {
TextInputEvent e{{event.text.text, std::strlen(event.text.text)}}; TextInputEvent e{event, {event.text.text, std::strlen(event.text.text)}};
textInputEvent(e); textInputEvent(e);
} break; } break;
case SDL_TEXTEDITING: { case SDL_TEXTEDITING: {
TextEditingEvent e{{event.edit.text, std::strlen(event.text.text)}, event.edit.start, event.edit.length}; TextEditingEvent e{event, {event.edit.text, std::strlen(event.text.text)}, event.edit.start, event.edit.length};
textEditingEvent(e); textEditingEvent(e);
} break; } break;
case SDL_QUIT: { case SDL_QUIT: {
ExitEvent e; ExitEvent e{event};
exitEvent(e); exitEvent(e);
if(e.isAccepted()) { if(e.isAccepted()) {
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
@ -731,6 +731,10 @@ void Sdl2Application::mainLoopIteration() {
return; return;
} }
} break; } break;
/* Direct everything else to anyEvent(), so users can implement
event handling for things not present in the Application APIs */
default: if(!(_flags & Flag::NoAnyEvent)) anyEvent(event);
} }
} }
@ -816,6 +820,12 @@ void Sdl2Application::tickEvent() {
_flags |= Flag::NoTickEvent; _flags |= Flag::NoTickEvent;
} }
void Sdl2Application::anyEvent(SDL_Event&) {
/* If this got called, the any event is not implemented by user and thus
we don't need to call it ever again */
_flags |= Flag::NoAnyEvent;
}
void Sdl2Application::viewportEvent(ViewportEvent& event) { void Sdl2Application::viewportEvent(ViewportEvent& event) {
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH CORRADE_IGNORE_DEPRECATED_PUSH

114
src/Magnum/Platform/Sdl2Application.h

@ -57,6 +57,10 @@
#include <wrl.h> /* For the WinMain entrypoint */ #include <wrl.h> /* For the WinMain entrypoint */
#endif #endif
#ifndef DOXYGEN_GENERATING_OUTPUT
union SDL_Event; /* for anyEvent() */
#endif
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
namespace Implementation { namespace Implementation {
@ -949,6 +953,17 @@ class Sdl2Application {
*/ */
virtual void tickEvent(); virtual void tickEvent();
/**
* @brief Any event
*
* Called in case a SDL event is not handled by any other event
* functions above.
* @see @ref ViewportEvent::event(), @ref InputEvent::event(),
* @ref MultiGestureEvent::event(), @ref TextInputEvent::event(),
* @ref TextEditingEvent::event(), @ref ExitEvent::event()
*/
virtual void anyEvent(SDL_Event& event);
/*@}*/ /*@}*/
private: private:
@ -956,12 +971,13 @@ class Sdl2Application {
Redraw = 1 << 0, Redraw = 1 << 0,
VSyncEnabled = 1 << 1, VSyncEnabled = 1 << 1,
NoTickEvent = 1 << 2, NoTickEvent = 1 << 2,
NoAnyEvent = 1 << 3,
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
Exit = 1 << 3 Exit = 1 << 4
#endif #endif
#ifdef CORRADE_TARGET_EMSCRIPTEN #ifdef CORRADE_TARGET_EMSCRIPTEN
TextInputActive = 1 << 4, TextInputActive = 1 << 5,
Resizable = 1 << 5 Resizable = 1 << 6
#endif #endif
}; };
@ -1667,11 +1683,20 @@ class Sdl2Application::ExitEvent {
*/ */
void setAccepted(bool accepted = true) { _accepted = accepted; } void setAccepted(bool accepted = true) { _accepted = accepted; }
/**
* @brief Underlying SDL event
*
* Of type `SDL_QUIT`.
* @see @ref Sdl2Application::anyEvent()
*/
const SDL_Event& event() const { return _event; }
private: private:
friend Sdl2Application; friend Sdl2Application;
explicit ExitEvent(): _accepted(false) {} explicit ExitEvent(const SDL_Event& event): _event(event), _accepted(false) {}
const SDL_Event& _event;
bool _accepted; bool _accepted;
}; };
@ -1725,11 +1750,33 @@ class Sdl2Application::ViewportEvent {
*/ */
Vector2 dpiScaling() const { return _dpiScaling; } Vector2 dpiScaling() const { return _dpiScaling; }
#ifndef CORRADE_TARGET_EMSCRIPTEN
/**
* @brief Underlying SDL event
*
* Of type `SDL_WINDOWEVENT`.
* @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten".
* @see @ref Sdl2Application::anyEvent()
*/
const SDL_Event& event() const { return _event; }
#endif
private: private:
friend Sdl2Application; friend Sdl2Application;
explicit ViewportEvent(const Vector2i& windowSize, const Vector2i& framebufferSize, const Vector2& dpiScaling): _windowSize{windowSize}, _framebufferSize{framebufferSize}, _dpiScaling{dpiScaling} {} explicit ViewportEvent(
#ifndef CORRADE_TARGET_EMSCRIPTEN
const SDL_Event& event,
#endif
const Vector2i& windowSize, const Vector2i& framebufferSize, const Vector2& dpiScaling):
#ifndef CORRADE_TARGET_EMSCRIPTEN
_event(event),
#endif
_windowSize{windowSize}, _framebufferSize{framebufferSize}, _dpiScaling{dpiScaling} {}
#ifndef CORRADE_TARGET_EMSCRIPTEN
const SDL_Event& _event;
#endif
const Vector2i _windowSize; const Vector2i _windowSize;
const Vector2i _framebufferSize; const Vector2i _framebufferSize;
const Vector2 _dpiScaling; const Vector2 _dpiScaling;
@ -1823,14 +1870,26 @@ class Sdl2Application::InputEvent {
*/ */
void setAccepted(bool accepted = true) { _accepted = accepted; } void setAccepted(bool accepted = true) { _accepted = accepted; }
/**
* @brief Underlying SDL event
*
* Of type `SDL_KEYDOWN` / `SDL_KEYUP` for @ref KeyEvent,
* `SDL_MOUSEBUTTONUP` / `SDL_MOUSEBUTTONDOWN` for @ref MouseEvent,
* `SDL_MOUSEWHEEL` for @ref MouseScrollEvent and `SDL_MOUSEMOTION` for
* @ref MouseMoveEvent.
* @see @ref Sdl2Application::anyEvent()
*/
const SDL_Event& event() const { return _event; }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
protected: protected:
explicit InputEvent(): _accepted(false) {} explicit InputEvent(const SDL_Event& event): _event(event), _accepted(false) {}
~InputEvent() = default; ~InputEvent() = default;
#endif #endif
private: private:
const SDL_Event& _event;
bool _accepted; bool _accepted;
}; };
@ -2050,7 +2109,7 @@ class Sdl2Application::KeyEvent: public Sdl2Application::InputEvent {
bool isRepeated() const { return _repeated; } bool isRepeated() const { return _repeated; }
private: private:
explicit KeyEvent(Key key, Modifiers modifiers, bool repeated): _key{key}, _modifiers{modifiers}, _repeated{repeated} {} explicit KeyEvent(const SDL_Event& event, Key key, Modifiers modifiers, bool repeated): InputEvent{event}, _key{key}, _modifiers{modifiers}, _repeated{repeated} {}
const Key _key; const Key _key;
const Modifiers _modifiers; const Modifiers _modifiers;
@ -2107,11 +2166,11 @@ class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent {
Modifiers modifiers(); Modifiers modifiers();
private: private:
explicit MouseEvent(Button button, const Vector2i& position explicit MouseEvent(const SDL_Event& event, Button button, const Vector2i& position
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
, Int clickCount , Int clickCount
#endif #endif
): _button{button}, _position{position}, ): InputEvent{event}, _button{button}, _position{position},
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
_clickCount{clickCount}, _clickCount{clickCount},
#endif #endif
@ -2180,7 +2239,7 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent {
Modifiers modifiers(); Modifiers modifiers();
private: private:
explicit MouseMoveEvent(const Vector2i& position, const Vector2i& relativePosition, Buttons buttons): _position{position}, _relativePosition{relativePosition}, _buttons{buttons}, _modifiersLoaded{false} {} explicit MouseMoveEvent(const SDL_Event& event, const Vector2i& position, const Vector2i& relativePosition, Buttons buttons): InputEvent{event}, _position{position}, _relativePosition{relativePosition}, _buttons{buttons}, _modifiersLoaded{false} {}
const Vector2i _position, _relativePosition; const Vector2i _position, _relativePosition;
const Buttons _buttons; const Buttons _buttons;
@ -2215,7 +2274,7 @@ class Sdl2Application::MouseScrollEvent: public Sdl2Application::InputEvent {
Modifiers modifiers(); Modifiers modifiers();
private: private:
explicit MouseScrollEvent(const Vector2& offset): _offset{offset}, _positionLoaded{false}, _modifiersLoaded{false} {} explicit MouseScrollEvent(const SDL_Event& event, const Vector2& offset): InputEvent{event}, _offset{offset}, _positionLoaded{false}, _modifiersLoaded{false} {}
const Vector2 _offset; const Vector2 _offset;
bool _positionLoaded; bool _positionLoaded;
@ -2283,9 +2342,18 @@ class Sdl2Application::MultiGestureEvent {
*/ */
Int fingerCount() const { return _fingerCount; } Int fingerCount() const { return _fingerCount; }
/**
* @brief Underlying SDL event
*
* Of type `SDL_MULTIGESTURE`.
* @see @ref Sdl2Application::anyEvent()
*/
const SDL_Event& event() const { return _event; }
private: private:
explicit MultiGestureEvent(const Vector2& center, Float relativeRotation, Float relativeDistance, Int fingerCount): _center{center}, _relativeRotation{relativeRotation}, _relativeDistance{relativeDistance}, _fingerCount{fingerCount}, _accepted{false} {} explicit MultiGestureEvent(const SDL_Event& event, const Vector2& center, Float relativeRotation, Float relativeDistance, Int fingerCount): _event(event), _center{center}, _relativeRotation{relativeRotation}, _relativeDistance{relativeDistance}, _fingerCount{fingerCount}, _accepted{false} {}
const SDL_Event& _event;
const Vector2 _center; const Vector2 _center;
const Float _relativeRotation; const Float _relativeRotation;
const Float _relativeDistance; const Float _relativeDistance;
@ -2330,9 +2398,18 @@ class Sdl2Application::TextInputEvent {
/** @brief Input text in UTF-8 */ /** @brief Input text in UTF-8 */
Containers::ArrayView<const char> text() const { return _text; } Containers::ArrayView<const char> text() const { return _text; }
/**
* @brief Underlying SDL event
*
* Of type `SDL_TEXTINPUT`.
* @see @ref Sdl2Application::anyEvent()
*/
const SDL_Event& event() const { return _event; }
private: private:
explicit TextInputEvent(Containers::ArrayView<const char> text): _text{text}, _accepted{false} {} explicit TextInputEvent(const SDL_Event& event, Containers::ArrayView<const char> text): _event(event), _text{text}, _accepted{false} {}
const SDL_Event& _event;
const Containers::ArrayView<const char> _text; const Containers::ArrayView<const char> _text;
bool _accepted; bool _accepted;
}; };
@ -2380,9 +2457,18 @@ class Sdl2Application::TextEditingEvent {
/** @brief Number of characters to edit from the start point */ /** @brief Number of characters to edit from the start point */
Int length() const { return _length; } Int length() const { return _length; }
/**
* @brief Underlying SDL event
*
* Of type `SDL_TEXTEDITING`.
* @see @ref Sdl2Application::anyEvent()
*/
const SDL_Event& event() const { return _event; }
private: private:
explicit TextEditingEvent(Containers::ArrayView<const char> text, Int start, Int length): _text{text}, _start{start}, _length{length}, _accepted{false} {} explicit TextEditingEvent(const SDL_Event& event, Containers::ArrayView<const char> text, Int start, Int length): _event(event), _text{text}, _start{start}, _length{length}, _accepted{false} {}
const SDL_Event& _event;
const Containers::ArrayView<const char> _text; const Containers::ArrayView<const char> _text;
const Int _start; const Int _start;
const Int _length; const Int _length;

8
src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp

@ -25,6 +25,8 @@
#include "Magnum/Platform/Sdl2Application.h" #include "Magnum/Platform/Sdl2Application.h"
#include <SDL_events.h>
namespace Magnum { namespace Platform { namespace Test { namespace { namespace Magnum { namespace Platform { namespace Test { namespace {
struct Sdl2ApplicationTest: Platform::Application { struct Sdl2ApplicationTest: Platform::Application {
@ -52,6 +54,12 @@ struct Sdl2ApplicationTest: Platform::Application {
void keyPressEvent(KeyEvent& event) override { void keyPressEvent(KeyEvent& event) override {
Debug{} << event.keyName(); Debug{} << event.keyName();
} }
/* Should fire on currently not handled events, such as minimize/maximize.
Comment out to verify correct behavior with the override not present. */
void anyEvent(SDL_Event& event) override {
Debug{} << "any event" << event.type;
}
}; };
}}}} }}}}

Loading…
Cancel
Save