rolmodl
C++ API for the Simple Directmedia Library 2 (SDL2)
Event.cpp
1 #include "hpp/Event.hpp"
2 
3 #include "hpp/Geom.hpp"
4 
5 #include <cstdio>
6 #include <cassert>
7 #include <algorithm>
8 #include <iterator>
9 
10 namespace rolmodl::event {
11  // fixme: only allow running in the main thread
12  std::optional<Event> poll() noexcept {
13  using std::variant;
14  using std::copy;
15  using std::begin;
16  using std::end;
17 
18  using namespace geom;
19 
20  SDL_Event e;
21  if (SDL_PollEvent(&e) == 0)
22  return std::nullopt;
23 
24  if (e.type == SDL_QUIT)
25  return Quit{{e.quit.timestamp}};
26  // if (e.type == SDL_USER) // todo: any non-recognized is a user event? keep track of registered events?
27  // return User{
28  // {e.user.timestamp},
29  // {e.user.windowID},
30  // .code = e.user.code,
31  // .data1 = e.user.data1,
32  // .data2 = e.user.data2
33  // };
34 
35  if (e.type == SDL_TEXTEDITING) {
36  Edit res{
37  {e.edit.timestamp},
38  {e.edit.windowID},
39  .start = e.edit.start,
40  .len = e.edit.length
41  };
42  copy(begin(e.edit.text), end(e.edit.text), begin(res.text));
43 
44  return res;
45  }
46  if (e.type == SDL_TEXTINPUT) {
47  #pragma clang diagnostic push
48  #pragma clang diagnostic ignored "-Wmissing-field-initializers"
49  Text res{
50  {e.text.timestamp},
51  {e.text.windowID},
52  };
53  copy(begin(e.text.text), end(e.text.text), begin(res.text));
54  #pragma clang diagnostic pop
55 
56  return res;
57  }
58 
59  if (e.type == SDL_FINGERMOTION)
60  return touch::Motion{
61  {e.tfinger.timestamp},
62  .touchId = e.tfinger.touchId,
63  .fingerId = e.tfinger.fingerId,
64 
65  .pos = geom::XYFloats{e.tfinger.x, e.tfinger.y},
66  .dpos = geom::XYFloats{e.tfinger.dx, e.tfinger.dy},
67  .pressure = e.tfinger.pressure
68  };
69  if (e.type == SDL_FINGERUP)
70  return touch::Up{
71  {e.tfinger.timestamp},
72  .touchId = e.tfinger.touchId,
73  .fingerId = e.tfinger.fingerId,
74 
75  .pos = geom::XYFloats{e.tfinger.x, e.tfinger.y},
76  .pressure = e.tfinger.pressure
77  };
78  if (e.type == SDL_FINGERDOWN)
79  return touch::Down{
80  {e.tfinger.timestamp},
81  .touchId = e.tfinger.touchId,
82  .fingerId = e.tfinger.fingerId,
83 
84  .pos = geom::XYFloats{e.tfinger.x, e.tfinger.y},
85  .pressure = e.tfinger.pressure
86  };
87 
88  if (e.type == SDL_KEYUP)
89  return key::Up{
90  {e.key.timestamp},
91  {e.key.windowID},
92  .state = button_state::unsafe::fromSDLEnum(e.key.state),
93  .repeat = e.key.repeat != 0,
94  .sym = Keysym{
95  .key = kb::key::unsafe::fromSDLEnum(e.key.keysym.sym),
96  .scancode = kb::scancode::unsafe::fromSDLEnum(e.key.keysym.scancode),
97  .mod = e.key.keysym.mod
98  }
99  };
100  if (e.type == SDL_KEYDOWN)
101  return key::Down{
102  {e.key.timestamp},
103  {e.key.windowID},
104  .state = button_state::unsafe::fromSDLEnum(e.key.state),
105  .repeat = e.key.repeat != 0,
106  .sym = Keysym{
107  .key = kb::key::unsafe::fromSDLEnum(e.key.keysym.sym),
108  .scancode = kb::scancode::unsafe::fromSDLEnum(e.key.keysym.scancode),
109  .mod = e.key.keysym.mod
110  }
111  };
112 
113  if (e.type == SDL_MOUSEBUTTONUP)
114  return mouse::button::Up{
115  {e.button.timestamp},
116  {e.button.windowID},
117  .mouseId = e.button.which,
118  .button = ::rolmodl::mouse::btn::unsafe::fromSDLEnum(e.button.button),
119  .state = button_state::unsafe::fromSDLEnum(e.button.state),
120  .clicks = e.button.clicks,
121  .pos = geom::XYInt32{e.button.x, e.button.y}
122  };
123  if (e.type == SDL_MOUSEBUTTONDOWN)
124  return mouse::button::Down{
125  {e.button.timestamp},
126  {e.button.windowID},
127  .mouseId = e.button.which,
128  .button = ::rolmodl::mouse::btn::unsafe::fromSDLEnum(e.button.button),
129  .state = button_state::unsafe::fromSDLEnum(e.button.state),
130  .clicks = e.button.clicks,
131  .pos = geom::XYInt32{e.button.x, e.button.y}
132  };
133  if (e.type == SDL_MOUSEMOTION)
134  return mouse::Motion{
135  {e.motion.timestamp},
136  {e.motion.windowID},
137  .mouseId = e.motion.which,
138  .state = ::rolmodl::mouse::BtnState(e.motion.state),
139  .pos = geom::XYInt32{e.motion.x, e.motion.y},
140  .dpos = geom::XYInt32{e.motion.xrel, e.motion.yrel}
141  };
142  if (e.type == SDL_MOUSEWHEEL)
143  return mouse::Wheel{
144  {e.wheel.timestamp},
145  {e.wheel.windowID},
146  .mouseId = e.wheel.which,
147  .dpos = geom::XYInt32{e.wheel.x, e.wheel.y},
148  .direction = mouse::wheel_direction::unsafe::fromSDLEnum(e.wheel.direction)
149  };
150 
151  if (e.type == SDL_JOYAXISMOTION)
152  return joystick::Axis{
153  {e.jaxis.timestamp},
154  .joystickId = e.jaxis.which,
155  .axisN = e.jaxis.axis,
156  .x = e.jaxis.value
157  };
158  if (e.type == SDL_JOYBALLMOTION)
159  return joystick::Ball{
160  {e.jball.timestamp},
161  .joystickId = e.jball.which,
162  .ballN = e.jball.ball,
163  .dx = e.jball.xrel, .dy = e.jball.yrel
164  };
165  if (e.type == SDL_JOYHATMOTION)
166  return joystick::Hat{
167  {e.jhat.timestamp},
168  .joystickId = e.jhat.which,
169  .hatN = e.jhat.hat,
170  .x = HatState(e.jhat.value)
171  };
172  if (e.type == SDL_JOYBUTTONUP)
173  return joystick::button::Up{
174  {e.jbutton.timestamp},
175  .joystickId = e.jbutton.which,
176  .buttonN = e.jbutton.button,
177  .state = button_state::unsafe::fromSDLEnum(e.jbutton.state)
178  };
179  if (e.type == SDL_JOYBUTTONDOWN)
180  return joystick::button::Down{
181  {e.jbutton.timestamp},
182  .joystickId = e.jbutton.which,
183  .buttonN = e.jbutton.button,
184  .state = button_state::unsafe::fromSDLEnum(e.jbutton.state)
185  };
186  if (e.type == SDL_JOYDEVICEADDED)
187  return joystick::device::Added{
188  {e.jdevice.timestamp},
189  .joystickId = e.jdevice.which,
190  };
191  if (e.type == SDL_JOYDEVICEREMOVED)
192  return joystick::device::Removed{
193  {e.jdevice.timestamp},
194  .joystickId = e.jdevice.which,
195  };
196 
197  if (e.type == SDL_CONTROLLERAXISMOTION)
198  return controller::Axis{
199  {e.caxis.timestamp},
200  .controllerId = e.caxis.which,
201  .axisN = e.caxis.axis,
202  .x = e.caxis.value
203  };
204  if (e.type == SDL_CONTROLLERBUTTONUP)
205  return controller::button::Up{
206  {e.cbutton.timestamp},
207  .controllerId = e.cbutton.which,
208  .buttonN = e.cbutton.button,
209  .state = button_state::unsafe::fromSDLEnum(e.cbutton.state)
210  };
211  if (e.type == SDL_CONTROLLERBUTTONDOWN)
212  return controller::button::Down{
213  {e.cbutton.timestamp},
214  .controllerId = e.cbutton.which,
215  .buttonN = e.cbutton.button,
216  .state = button_state::unsafe::fromSDLEnum(e.cbutton.state)
217  };
218  if (e.type == SDL_CONTROLLERDEVICEADDED)
219  return controller::device::Added{
220  {e.cdevice.timestamp},
221  .controllerId = e.cdevice.which,
222  };
223  if (e.type == SDL_CONTROLLERDEVICEREMOVED)
224  return controller::device::Removed{
225  {e.cdevice.timestamp},
226  .controllerId = e.cdevice.which,
227  };
228  if (e.type == SDL_CONTROLLERDEVICEREMAPPED)
229  return controller::device::Remapped{
230  {e.cdevice.timestamp},
231  .controllerId = e.cdevice.which,
232  };
233 
234  if (e.type == SDL_MULTIGESTURE)
235  return gesture::Builtin{
236  {e.mgesture.timestamp},
237  .touchId = e.mgesture.touchId,
238 
239  .dRotation = e.mgesture.dTheta,
240  .dPinch = e.mgesture.dDist,
241 
242  .nFingers = e.mgesture.numFingers,
243  .pos = geom::XYFloats{e.mgesture.x, e.mgesture.y}
244  };
245  if (e.type == SDL_DOLLARRECORD)
246  return gesture::custom::Recorded{
247  {e.dgesture.timestamp},
248  .touchId = e.dgesture.touchId,
249  .gestureId = e.dgesture.gestureId,
250 
251  .nFingers = e.dgesture.numFingers,
252  .error = e.dgesture.error,
253  .pos = geom::XYFloats{e.mgesture.x, e.mgesture.y}
254  };
255  if (e.type == SDL_DOLLARGESTURE)
256  return gesture::custom::Detected{
257  {e.dgesture.timestamp},
258  .touchId = e.dgesture.touchId,
259  .gestureId = e.dgesture.gestureId,
260 
261  .nFingers = e.dgesture.numFingers,
262  .error = e.dgesture.error,
263  .pos = geom::XYFloats{e.mgesture.x, e.mgesture.y}
264  };
265 
266  if (e.type == SDL_WINDOWEVENT) {
267  if (e.window.event == SDL_WINDOWEVENT_CLOSE)
268  return window::Close{{e.window.timestamp}, {e.window.windowID}};
269  if (e.window.event == SDL_WINDOWEVENT_HIT_TEST)
270  return window::HitTest{{e.window.timestamp}, {e.window.windowID}};
271 
272  if (e.window.event == SDL_WINDOWEVENT_SHOWN)
273  return window::Shown{{e.window.timestamp}, {e.window.windowID}};
274  if (e.window.event == SDL_WINDOWEVENT_HIDDEN)
275  return window::Hidden{{e.window.timestamp}, {e.window.windowID}};
276  if (e.window.event == SDL_WINDOWEVENT_EXPOSED)
277  return window::Exposed{{e.window.timestamp}, {e.window.windowID}};
278 
279  if (e.window.event == SDL_WINDOWEVENT_MOVED)
280  return window::Moved{
281  {e.window.timestamp}, {e.window.windowID},
282  .loc = Pos{static_cast<int>(e.window.data1), static_cast<int>(e.window.data2)} // todo: make sure we want to cast
283  };
284  if (e.window.event == SDL_WINDOWEVENT_RESIZED)
285  return window::Resized{
286  {e.window.timestamp}, {e.window.windowID},
287  .size = Size{static_cast<int>(e.window.data1), static_cast<int>(e.window.data2)} // todo: make sure we want to cast
288  };
289  if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
290  return window::SizeChanged{
291  {e.window.timestamp}, {e.window.windowID},
292  .size = Size{static_cast<int>(e.window.data1), static_cast<int>(e.window.data2)} // todo: make sure we want to cast
293  };
294 
295  if (e.window.event == SDL_WINDOWEVENT_MINIMIZED)
296  return window::Minimized{{e.window.timestamp}, {e.window.windowID}};
297  if (e.window.event == SDL_WINDOWEVENT_MAXIMIZED)
298  return window::Maximized{{e.window.timestamp}, {e.window.windowID}};
299  if (e.window.event == SDL_WINDOWEVENT_RESTORED)
300  return window::Restored{{e.window.timestamp}, {e.window.windowID}};
301 
302  if (e.window.event == SDL_WINDOWEVENT_ENTER)
303  return window::mouse::Entered{{e.window.timestamp}, {e.window.windowID}};
304  if (e.window.event == SDL_WINDOWEVENT_LEAVE)
305  return window::mouse::Left{{e.window.timestamp}, {e.window.windowID}};
306 
307  if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
308  return window::focus::Gained{{e.window.timestamp}, {e.window.windowID}};
309  if (e.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
310  return window::focus::Lost{{e.window.timestamp}, {e.window.windowID}};
311  if (e.window.event == SDL_WINDOWEVENT_TAKE_FOCUS)
312  return window::focus::Offered{{e.window.timestamp}, {e.window.windowID}};
313  }
314 
315  if (e.type == SDL_SYSWMEVENT)
316  return SystemWindow{
317  {e.syswm.timestamp},
318  .msg = e.syswm.msg
319  };
320 
321  if (e.type == SDL_DROPFILE)
322  return drag_n_drop::File{
323  {e.drop.timestamp},
324  {e.drop.windowID},
325  .path = SDLString(e.drop.file)
326  };
327  if (e.type == SDL_DROPTEXT)
328  return drag_n_drop::Text{
329  {e.drop.timestamp},
330  {e.drop.windowID},
331  .x = SDLString(e.drop.file)
332  };
333  if (e.type == SDL_DROPBEGIN)
334  return drag_n_drop::Begin{{e.drop.timestamp}, {e.drop.windowID}};
335  if (e.type == SDL_DROPCOMPLETE)
336  return drag_n_drop::Complete{{e.drop.timestamp}, {e.drop.windowID}};
337 
338  if (e.type == SDL_AUDIODEVICEADDED)
339  return audio_device::Added{
340  {e.adevice.timestamp},
341  .index = e.adevice.which,
342  .isCapture = e.adevice.iscapture != 0
343  };
344  if (e.type == SDL_AUDIODEVICEREMOVED)
345  return audio_device::Removed{
346  {e.adevice.timestamp},
347  .id = e.adevice.which,
348  .isCapture = e.adevice.iscapture != 0
349  };
350 
351  return std::nullopt;
352  }
353 }
iterator
Geom.hpp
algorithm
rolmodl::mouse::BtnState
Definition: Mouse.hpp:159
std::nullopt
T nullopt
std::copy
T copy(T... args)
std::begin
T begin(T... args)
cassert
std::optional
std::end
T end(T... args)
cstdio
std::variant