cpp-sdl2
C++ header-only SDL2 wrapper
event.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "exception.hpp"
4 
5 #include <SDL.h>
6 #include <SDL_events.h>
7 
8 #include <functional>
9 #include <map>
10 #include <vector>
11 
12 #include <begin_code.h> // use SDL2 packing
13 
14 // Visual Studio 2019 has became TOO pedantic about member
15 // initialization. Supress IntelliSence CppCoreGuideline
16 // "MEMBER_UNINIT" warning. The static ananlyser doesn't like our union
17 // initialized only by writing over the whole object with the value of an
18 // SDL_Event. Have to agree with it on the fact that this is using dark magic
19 // **BUT** we actually **KNOW** what we are doing here, thank you very much
20 #if _MSC_VER >= 1910
21 #pragma warning(push)
22 #pragma warning(disable : 26495)
23 #endif
24 
25 namespace sdl
26 {
32 union Event
33 {
34  // this is copy-pasted from the definition of SDL_Event in
35  // <SDL2/SDL_events.h>
36 public:
37  Uint32 type;
38  SDL_CommonEvent common;
39  SDL_WindowEvent window;
40  SDL_KeyboardEvent key;
41  SDL_TextEditingEvent edit;
42  SDL_TextInputEvent text;
43  SDL_MouseMotionEvent motion;
44  SDL_MouseButtonEvent button;
45  SDL_MouseWheelEvent wheel;
46  SDL_JoyAxisEvent jaxis;
47  SDL_JoyBallEvent jball;
48  SDL_JoyHatEvent jhat;
49  SDL_JoyButtonEvent jbutton;
50  SDL_JoyDeviceEvent jdevice;
51  SDL_ControllerAxisEvent caxis;
52  SDL_ControllerButtonEvent cbutton;
53  SDL_ControllerDeviceEvent cdevice;
54  SDL_AudioDeviceEvent adevice;
55  SDL_QuitEvent quit;
56  SDL_UserEvent user;
57  SDL_SysWMEvent syswm;
58  SDL_TouchFingerEvent tfinger;
59  SDL_MultiGestureEvent mgesture;
60  SDL_DollarGestureEvent dgesture;
61  SDL_DropEvent drop;
62 #if SDL_VERSION_ATLEAST(2, 0, 9)
63  SDL_SensorEvent sensor;
64  SDL_DisplayEvent display;
65 #endif
66 
67  /*
68  This is necessary for ABI compatibility between Visual C++ and GCC
69  Visual C++ will respect the push pack pragma and use 52 bytes for
70  this structure, and GCC will use the alignment of the largest datatype
71  within the union, which is 8 bytes.
72 
73  So... we'll add padding to force the size to be 56 bytes for both.
74  */
75  Uint8 padding[56];
76 
79  {
80  // statically checks the likelyness of this union to lineup with the C
81  // union
82  static_assert(
83  sizeof(Event) == sizeof(SDL_Event),
84  "Hey, it's likely that the bits in sdl::Event and SDL_Event don't "
85  "lineup. Please check you are using a supported version of SDL2!!");
86 
87  static_assert(offsetof(Event, common.timestamp) == offsetof(SDL_Event, common.timestamp));
88 
89  static_assert(offsetof(Event, user.windowID) == offsetof(SDL_Event, user.windowID));
90 
91  memset(this, 0, sizeof(SDL_Event));
92  }
93 
95  Event(SDL_Event const& e) : Event{*reinterpret_cast<Event const*>(&e)} {}
96 
98  static Event const& ref_from(SDL_Event const& e) { return *reinterpret_cast<Event const*>(&e); }
99 
101  static Event& ref_from(SDL_Event& e) { return *reinterpret_cast<Event*>(&e); }
102 
104  static Event const& ref_from(SDL_Event const* e) { return *reinterpret_cast<Event const*>(e); }
105 
107  static Event& ref_from(SDL_Event* e) { return *reinterpret_cast<Event*>(e); }
108 
110  operator SDL_Event() const { return *reinterpret_cast<SDL_Event const*>(this); }
111 
113  SDL_Event const* ptr() const { return reinterpret_cast<SDL_Event const*>(this); }
114 
116  SDL_Event* ptr() { return reinterpret_cast<SDL_Event*>(this); }
117 
119  enum class State : int
120  {
121  Query = SDL_QUERY,
122  Ignore = SDL_IGNORE,
123  Enable = SDL_ENABLE,
124  };
125 
127  bool poll() { return SDL_PollEvent(ptr()); }
128 
130  void wait()
131  {
132  if (!SDL_WaitEvent(ptr())) throw Exception{"SDL_WaitEvent"};
133  }
134 
137  void wait(int timeout)
138  {
139  if (!SDL_WaitEventTimeout(ptr(), timeout))
140  {
141  throw Exception{"SDL_WaitEventTimeout"};
142  }
143  }
144 
146  void push() const
147  {
148  // SDL_PushEvent won't modify it's argument
149  if (!SDL_PushEvent(const_cast<SDL_Event*>(ptr())))
150  {
151  throw Exception{"SDL_PushEvent"};
152  }
153  }
154 
156  void peek()
157  {
158  if (SDL_PeepEvents(ptr(), 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) < 0)
159  {
160  throw Exception{"SDL_PeepEvents"};
161  }
162  }
163 
165  inline bool has_events() { return SDL_HasEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); }
166 
169  inline bool has_events(Uint32 type) { return SDL_HasEvent(type); }
170 
174  inline bool has_events(Uint32 minType, Uint32 maxType)
175  {
176  return SDL_HasEvents(minType, maxType);
177  }
178 
181  inline void pump_events() { SDL_PumpEvents(); }
182 
186  inline void flush_events(Uint32 minType, Uint32 maxType) { SDL_FlushEvents(minType, maxType); }
187 
189  inline void flush_events() { flush_events(SDL_FIRSTEVENT, SDL_LASTEVENT); }
190 
192  inline void flush_events(Uint32 type) { flush_events(type, type); }
193 
198  inline void add_events(std::vector<Event> const& events, Uint32 minType, Uint32 maxType)
199  {
200  // This use of SDL_PeepEvents don't modify the events
201  auto array = const_cast<SDL_Event*>(reinterpret_cast<SDL_Event const*>(&events[0]));
202  if (SDL_PeepEvents(array, int(events.size()), SDL_ADDEVENT, minType, maxType) < 0)
203  {
204  throw Exception{"SDL_PeepEvents"};
205  }
206  }
207 
210  inline void add_events(std::vector<Event> const& events)
211  {
212  add_events(events, SDL_FIRSTEVENT, SDL_LASTEVENT);
213  }
214 
218  inline void add_events(std::vector<Event> const& events, Uint32 type)
219  {
220  add_events(events, type, type);
221  }
222 
227  inline std::vector<Event> peek_events(size_t maxEvents, Uint32 minType, Uint32 maxType)
228  {
229  auto res = std::vector<Event>(maxEvents);
230  auto array = reinterpret_cast<SDL_Event*>(&res[0]);
231  if (SDL_PeepEvents(array, int(maxEvents), SDL_PEEKEVENT, minType, maxType) < 0)
232  {
233  throw Exception{"SDL_PeepEvents"};
234  }
235  return res;
236  }
237 
239  inline std::vector<Event> peek_events(size_t maxEvents)
240  {
241  return peek_events(maxEvents, SDL_FIRSTEVENT, SDL_LASTEVENT);
242  }
243 
246  inline std::vector<Event> peek_events(size_t maxEvents, Uint32 type)
247  {
248  return peek_events(maxEvents, type, type);
249  }
250 
255  inline std::vector<Event> get_events(size_t maxEvents, Uint32 minType, Uint32 maxType)
256  {
257  auto res = std::vector<Event>(maxEvents);
258  auto array = reinterpret_cast<SDL_Event*>(&res[0]);
259  if (SDL_PeepEvents(array, int(maxEvents), SDL_GETEVENT, minType, maxType) < 0)
260  {
261  throw Exception{"SDL_PeepEvents"};
262  }
263  return res;
264  }
265 
269  inline std::vector<Event> get_events(size_t maxEvents)
270  {
271  return get_events(maxEvents, SDL_FIRSTEVENT, SDL_LASTEVENT);
272  }
273 
277  inline std::vector<Event> get_events(size_t maxEvents, Uint32 type)
278  {
279  return get_events(maxEvents, type, type);
280  }
281 
283  struct EventFilter
284  {
285  using func_type = bool (*)(void*, Event&);
286 
287  void* userdata_ = nullptr;
288  func_type filter_ = nullptr;
289  bool isWatcher_ = false;
290 
291  EventFilter(func_type filter, void* userdata) : filter_{filter}, userdata_{userdata} {}
292 
293  EventFilter(func_type filter) : filter_{filter} {}
294 
296  {
297  if (isWatcher_) del_watcher();
298  }
299 
300  static int call_filter(void* data, SDL_Event* event)
301  {
302  auto filter = static_cast<EventFilter*>(data);
303  return filter->filter_(filter->userdata_, sdl::Event::ref_from(event));
304  }
305 
306  void filter_queue() { SDL_FilterEvents(&call_filter, this); }
307 
308  void set() { SDL_SetEventFilter(&call_filter, userdata_); }
309 
310  static void unset() { SDL_FilterEvents(nullptr, nullptr); }
311 
312  void add_watcher()
313  {
314  SDL_AddEventWatch(&call_filter, this);
315  isWatcher_ = true;
316  }
317 
318  void del_watcher()
319  {
320  SDL_DelEventWatch(&call_filter, this);
321  isWatcher_ = false;
322  }
323  };
324 
325  inline Event::State event_state(Uint32 type)
326  {
327  return static_cast<Event::State>(SDL_GetEventState(type));
328  }
329 
330  inline void set_event_state(Uint32 type, Event::State state)
331  {
332  SDL_EventState(type, int(state));
333  }
334 };
335 } // namespace sdl
336 
337 #include <close_code.h>
338 
339 #if _MSC_VER >= 1910
340 #pragma warning(pop)
341 #endif
void flush_events()
Clear all events from the event queue.
Definition: event.hpp:189
SDL_ControllerButtonEvent cbutton
Game Controller button event data.
Definition: event.hpp:52
SDL_SensorEvent sensor
Definition: event.hpp:63
SDL_DisplayEvent display
Sensor event data.
Definition: event.hpp:64
SDL_JoyHatEvent jhat
Joystick hat event data.
Definition: event.hpp:48
static Event const & ref_from(SDL_Event const *e)
& ref_from(SDL_Event const* e)
Definition: event.hpp:104
std::vector< Event > get_events(size_t maxEvents)
Get events from the queue.
Definition: event.hpp:269
SDL_ControllerAxisEvent caxis
Game Controller axis event data.
Definition: event.hpp:51
SDL_JoyAxisEvent jaxis
Joystick axis event data.
Definition: event.hpp:46
void wait()
Wait until next event occur. This will stop the execution of your code until something happens...
Definition: event.hpp:130
Event filter object.
Definition: event.hpp:283
SDL_CommonEvent common
Common event data.
Definition: event.hpp:38
std::vector< Event > peek_events(size_t maxEvents, Uint32 minType, Uint32 maxType)
Peek at multiple future events.
Definition: event.hpp:227
static Event & ref_from(SDL_Event *e)
ref_from(SDL_Event& e)
Definition: event.hpp:107
void wait(int timeout)
Wait until next event occur, or until the given duration expired.
Definition: event.hpp:137
SDL_AudioDeviceEvent adevice
Audio device event data.
Definition: event.hpp:54
SDL_WindowEvent window
Window event data.
Definition: event.hpp:39
SDL_MultiGestureEvent mgesture
Gesture event data.
Definition: event.hpp:59
Uint32 type
Event type, shared with all events.
Definition: event.hpp:37
void add_events(std::vector< Event > const &events)
Add events to the queue.
Definition: event.hpp:210
bool has_events(Uint32 type)
Return true if there are events of a specific type in the queue.
Definition: event.hpp:169
Event::State event_state(Uint32 type)
Definition: event.hpp:325
bool has_events()
Return true if there are events in the queue.
Definition: event.hpp:165
SDL_MouseWheelEvent wheel
Mouse wheel event data.
Definition: event.hpp:45
SDL_MouseMotionEvent motion
Mouse motion event data.
Definition: event.hpp:43
SDL_SysWMEvent syswm
System dependent window event data.
Definition: event.hpp:57
SDL_KeyboardEvent key
Keyboard event data.
Definition: event.hpp:40
Object that represent an event captured by SDL.
Definition: event.hpp:32
SDL_DollarGestureEvent dgesture
Gesture event data.
Definition: event.hpp:60
SDL_MouseButtonEvent button
Mouse button event data.
Definition: event.hpp:44
SDL_TextEditingEvent edit
Text editing event data.
Definition: event.hpp:41
bool poll()
Pool for events, return false when there are no more events to poll.
Definition: event.hpp:127
Event()
Default ctor an event.
Definition: event.hpp:78
static int call_filter(void *data, SDL_Event *event)
Definition: event.hpp:300
bool(*)(void *, Event &) func_type
Definition: event.hpp:285
SDL_Event * ptr()
Get a pointer to an SDL_Event.
Definition: event.hpp:116
void peek()
Peek the next event in the list.
Definition: event.hpp:156
void flush_events(Uint32 minType, Uint32 maxType)
Clear events of a range of types from the event queue.
Definition: event.hpp:186
SDL_QuitEvent quit
Quit request event data.
Definition: event.hpp:55
Define to deactivate exception support.
Definition: color.hpp:7
void push() const
Push the current event to the list of event to process.
Definition: event.hpp:146
State
For type safety, we will use these scoped enum values instead of raw numbers like the C api...
Definition: event.hpp:119
void pump_events()
Pump the event loop from the OS event system.
Definition: event.hpp:181
SDL_JoyBallEvent jball
Joystick ball event data.
Definition: event.hpp:47
SDL_Event const * ptr() const
Get a pointer to an SDL_Event.
Definition: event.hpp:113
bool has_events(Uint32 minType, Uint32 maxType)
Return true if there are events of a specific range of types in the queue.
Definition: event.hpp:174
std::vector< Event > peek_events(size_t maxEvents)
Peek at future events.
Definition: event.hpp:239
SDL_ControllerDeviceEvent cdevice
Game Controller device event data.
Definition: event.hpp:53
std::vector< Event > get_events(size_t maxEvents, Uint32 type)
Get events from a specific type.
Definition: event.hpp:277
SDL_TouchFingerEvent tfinger
Touch finger event data.
Definition: event.hpp:58
std::vector< Event > get_events(size_t maxEvents, Uint32 minType, Uint32 maxType)
Get events from the queue maxEvents max number of events to get.
Definition: event.hpp:255
void add_events(std::vector< Event > const &events, Uint32 minType, Uint32 maxType)
Add events of a specific range of types to the event queue.
Definition: event.hpp:198
SDL_DropEvent drop
Drag and drop event data.
Definition: event.hpp:61
static void unset()
Definition: event.hpp:310
SDL_TextInputEvent text
Text input event data.
Definition: event.hpp:42
static Event const & ref_from(SDL_Event const &e)
Get a const reference to an sdl::Event from an SDL_Event.
Definition: event.hpp:98
std::vector< Event > peek_events(size_t maxEvents, Uint32 type)
Peek events from a specific type.
Definition: event.hpp:246
EventFilter(func_type filter)
Definition: event.hpp:293
SDL_JoyButtonEvent jbutton
Joystick button event data.
Definition: event.hpp:49
SDL_UserEvent user
Custom event data.
Definition: event.hpp:56
void flush_events(Uint32 type)
Clear events from a specific type from the event queue.
Definition: event.hpp:192
static Event & ref_from(SDL_Event &e)
Get a non-const reference to an sdl::Event from an SDL_Event.
Definition: event.hpp:101
Event(SDL_Event const &e)
converting ctor to create an sdl::Event from an SDL_Event struct
Definition: event.hpp:95
Define to deactivate exception support.
Definition: exception.hpp:21
void add_events(std::vector< Event > const &events, Uint32 type)
Add events of a specific type to the queue.
Definition: event.hpp:218
state
Power states.
Definition: utils.hpp:148
SDL_JoyDeviceEvent jdevice
Joystick device change event data.
Definition: event.hpp:50
Uint8 padding[56]
Window event data.
Definition: event.hpp:75
void set_event_state(Uint32 type, Event::State state)
Definition: event.hpp:330
EventFilter(func_type filter, void *userdata)
Definition: event.hpp:291