1 /**
2  * Retrograde Engine
3  *
4  * Authors:
5  *  Mike Bierlee, m.bierlee@lostmoment.com
6  * Copyright: 2014-2021 Mike Bierlee
7  * License:
8  *  This software is licensed under the terms of the MIT license.
9  *  The full terms of the license can be found in the LICENSE.txt file.
10  */
11 
12 module retrograde.sdl2.event;
13 
14 version(Have_derelict_sdl2) {
15 
16 import retrograde.messaging;
17 import retrograde.engine;
18 import retrograde.sdl2.input;
19 import retrograde.input;
20 
21 import poodinis;
22 
23 import derelict.sdl2.sdl;
24 
25 class Sdl2EventHandler : EventHandler {
26 
27     private immutable JoystickHatPosition[ubyte] hatMap;
28     private KeyboardKeyCode[SDL_Scancode] scanCodeMap;
29     private MouseButton[ubyte] mouseButtonMap;
30     private bool previouslyHandledMouseMotionEvent = false;
31 
32     @Autowire
33     private Sdl2InputDeviceManager inputDeviceManager;
34 
35     @Autowire
36     private RawInputEventChannel rawInputEventChannel;
37 
38     @Autowire
39     private CoreEngineCommandChannel coreEngineCommandChannel;
40 
41     private const int mouseMotionMax = 60;
42 
43     public this() {
44         hatMap = [
45             SDL_HAT_LEFTUP: JoystickHatPosition.LEFT_UP,
46             SDL_HAT_LEFT: JoystickHatPosition.LEFT,
47             SDL_HAT_LEFTDOWN: JoystickHatPosition.LEFT_DOWN,
48             SDL_HAT_UP: JoystickHatPosition.UP,
49             SDL_HAT_CENTERED: JoystickHatPosition.CENTERED,
50             SDL_HAT_DOWN: JoystickHatPosition.DOWN,
51             SDL_HAT_RIGHTUP: JoystickHatPosition.RIGHT_UP,
52             SDL_HAT_RIGHT: JoystickHatPosition.RIGHT,
53             SDL_HAT_RIGHTDOWN: JoystickHatPosition.RIGHT_DOWN
54         ];
55 
56         scanCodeMap = [
57             SDL_SCANCODE_A: KeyboardKeyCode.A,
58             SDL_SCANCODE_B: KeyboardKeyCode.B,
59             SDL_SCANCODE_C: KeyboardKeyCode.C,
60             SDL_SCANCODE_D: KeyboardKeyCode.D,
61             SDL_SCANCODE_E: KeyboardKeyCode.E,
62             SDL_SCANCODE_F: KeyboardKeyCode.F,
63             SDL_SCANCODE_G: KeyboardKeyCode.G,
64             SDL_SCANCODE_H: KeyboardKeyCode.H,
65             SDL_SCANCODE_I: KeyboardKeyCode.I,
66             SDL_SCANCODE_J: KeyboardKeyCode.J,
67             SDL_SCANCODE_K: KeyboardKeyCode.K,
68             SDL_SCANCODE_L: KeyboardKeyCode.L,
69             SDL_SCANCODE_M: KeyboardKeyCode.M,
70             SDL_SCANCODE_N: KeyboardKeyCode.N,
71             SDL_SCANCODE_O: KeyboardKeyCode.O,
72             SDL_SCANCODE_P: KeyboardKeyCode.P,
73             SDL_SCANCODE_Q: KeyboardKeyCode.Q,
74             SDL_SCANCODE_R: KeyboardKeyCode.R,
75             SDL_SCANCODE_S: KeyboardKeyCode.S,
76             SDL_SCANCODE_T: KeyboardKeyCode.T,
77             SDL_SCANCODE_U: KeyboardKeyCode.U,
78             SDL_SCANCODE_V: KeyboardKeyCode.V,
79             SDL_SCANCODE_W: KeyboardKeyCode.W,
80             SDL_SCANCODE_X: KeyboardKeyCode.X,
81             SDL_SCANCODE_Y: KeyboardKeyCode.Y,
82             SDL_SCANCODE_Z: KeyboardKeyCode.Z,
83 
84             SDL_SCANCODE_1: KeyboardKeyCode.ONE,
85             SDL_SCANCODE_2: KeyboardKeyCode.TWO,
86             SDL_SCANCODE_3: KeyboardKeyCode.THREE,
87             SDL_SCANCODE_4: KeyboardKeyCode.FOUR,
88             SDL_SCANCODE_5: KeyboardKeyCode.FIVE,
89             SDL_SCANCODE_6: KeyboardKeyCode.SIX,
90             SDL_SCANCODE_7: KeyboardKeyCode.SEVEN,
91             SDL_SCANCODE_8: KeyboardKeyCode.EIGHT,
92             SDL_SCANCODE_9: KeyboardKeyCode.NINE,
93             SDL_SCANCODE_0: KeyboardKeyCode.ZERO,
94 
95             SDL_SCANCODE_RETURN: KeyboardKeyCode.RETURN,
96             SDL_SCANCODE_ESCAPE: KeyboardKeyCode.ESCAPE,
97             SDL_SCANCODE_BACKSPACE: KeyboardKeyCode.BACKSPACE,
98             SDL_SCANCODE_TAB:  KeyboardKeyCode.TAB,
99             SDL_SCANCODE_SPACE:  KeyboardKeyCode.SPACE,
100 
101             SDL_SCANCODE_MINUS: KeyboardKeyCode.MINUS,
102             SDL_SCANCODE_EQUALS: KeyboardKeyCode.EQUALS,
103             SDL_SCANCODE_LEFTBRACKET: KeyboardKeyCode.LEFTBRACKET,
104             SDL_SCANCODE_RIGHTBRACKET: KeyboardKeyCode.RIGHTBRACKET,
105             SDL_SCANCODE_BACKSLASH: KeyboardKeyCode.BACKSLASH,
106             SDL_SCANCODE_NONUSHASH: KeyboardKeyCode.NONUSHASH,
107             SDL_SCANCODE_SEMICOLON: KeyboardKeyCode.SEMICOLON,
108             SDL_SCANCODE_APOSTROPHE: KeyboardKeyCode.APOSTROPHE,
109             SDL_SCANCODE_GRAVE: KeyboardKeyCode.GRAVE,
110             SDL_SCANCODE_COMMA: KeyboardKeyCode.COMMA,
111             SDL_SCANCODE_PERIOD: KeyboardKeyCode.PERIOD,
112             SDL_SCANCODE_SLASH: KeyboardKeyCode.SLASH,
113 
114             SDL_SCANCODE_CAPSLOCK: KeyboardKeyCode.CAPSLOCK,
115 
116             SDL_SCANCODE_F1: KeyboardKeyCode.F1,
117             SDL_SCANCODE_F2: KeyboardKeyCode.F2,
118             SDL_SCANCODE_F3: KeyboardKeyCode.F3,
119             SDL_SCANCODE_F4: KeyboardKeyCode.F4,
120             SDL_SCANCODE_F5: KeyboardKeyCode.F5,
121             SDL_SCANCODE_F6: KeyboardKeyCode.F6,
122             SDL_SCANCODE_F7: KeyboardKeyCode.F7,
123             SDL_SCANCODE_F8: KeyboardKeyCode.F8,
124             SDL_SCANCODE_F9: KeyboardKeyCode.F9,
125             SDL_SCANCODE_F10: KeyboardKeyCode.F10,
126             SDL_SCANCODE_F11: KeyboardKeyCode.F11,
127             SDL_SCANCODE_F12: KeyboardKeyCode.F12,
128 
129             SDL_SCANCODE_PRINTSCREEN: KeyboardKeyCode.PRINTSCREEN,
130             SDL_SCANCODE_SCROLLLOCK: KeyboardKeyCode.SCROLLLOCK,
131             SDL_SCANCODE_PAUSE: KeyboardKeyCode.PAUSE,
132             SDL_SCANCODE_INSERT: KeyboardKeyCode.INSERT,
133             SDL_SCANCODE_HOME: KeyboardKeyCode.HOME,
134             SDL_SCANCODE_PAGEUP: KeyboardKeyCode.PAGEUP,
135             SDL_SCANCODE_DELETE: KeyboardKeyCode.DELETE,
136             SDL_SCANCODE_END: KeyboardKeyCode.END,
137             SDL_SCANCODE_PAGEDOWN: KeyboardKeyCode.PAGEDOWN,
138             SDL_SCANCODE_RIGHT: KeyboardKeyCode.RIGHT,
139             SDL_SCANCODE_LEFT: KeyboardKeyCode.LEFT,
140             SDL_SCANCODE_DOWN: KeyboardKeyCode.DOWN,
141             SDL_SCANCODE_UP: KeyboardKeyCode.UP,
142 
143             SDL_SCANCODE_NUMLOCKCLEAR: KeyboardKeyCode.NUMLOCKCLEAR,
144             SDL_SCANCODE_KP_DIVIDE: KeyboardKeyCode.KEYPAD_DIVIDE,
145             SDL_SCANCODE_KP_MULTIPLY: KeyboardKeyCode.KEYPAD_MULTIPLY,
146             SDL_SCANCODE_KP_MINUS: KeyboardKeyCode.KEYPAD_MINUS,
147             SDL_SCANCODE_KP_PLUS: KeyboardKeyCode.KEYPAD_PLUS,
148             SDL_SCANCODE_KP_ENTER: KeyboardKeyCode.KEYPAD_ENTER,
149             SDL_SCANCODE_KP_1: KeyboardKeyCode.KEYPAD_ONE,
150             SDL_SCANCODE_KP_2: KeyboardKeyCode.KEYPAD_TWO,
151             SDL_SCANCODE_KP_3: KeyboardKeyCode.KEYPAD_THREE,
152             SDL_SCANCODE_KP_4: KeyboardKeyCode.KEYPAD_FOUR,
153             SDL_SCANCODE_KP_5: KeyboardKeyCode.KEYPAD_FIVE,
154             SDL_SCANCODE_KP_6: KeyboardKeyCode.KEYPAD_SIX,
155             SDL_SCANCODE_KP_7: KeyboardKeyCode.KEYPAD_SEVEN,
156             SDL_SCANCODE_KP_8: KeyboardKeyCode.KEYPAD_EIGHT,
157             SDL_SCANCODE_KP_9: KeyboardKeyCode.KEYPAD_NINE,
158             SDL_SCANCODE_KP_0: KeyboardKeyCode.KEYPAD_ZERO,
159             SDL_SCANCODE_KP_PERIOD: KeyboardKeyCode.KEYPAD_PERIOD,
160 
161             SDL_SCANCODE_NONUSBACKSLASH: KeyboardKeyCode.NONUSBACKSLASH,
162             SDL_SCANCODE_APPLICATION: KeyboardKeyCode.APPLICATION,
163             SDL_SCANCODE_POWER: KeyboardKeyCode.POWER,
164             SDL_SCANCODE_KP_EQUALS: KeyboardKeyCode.KEYPAD_EQUALS,
165             SDL_SCANCODE_F13: KeyboardKeyCode.F13,
166             SDL_SCANCODE_F14: KeyboardKeyCode.F14,
167             SDL_SCANCODE_F15: KeyboardKeyCode.F15,
168             SDL_SCANCODE_F16: KeyboardKeyCode.F16,
169             SDL_SCANCODE_F17: KeyboardKeyCode.F17,
170             SDL_SCANCODE_F18: KeyboardKeyCode.F18,
171             SDL_SCANCODE_F19: KeyboardKeyCode.F19,
172             SDL_SCANCODE_F20: KeyboardKeyCode.F20,
173             SDL_SCANCODE_F21: KeyboardKeyCode.F21,
174             SDL_SCANCODE_F22: KeyboardKeyCode.F22,
175             SDL_SCANCODE_F23: KeyboardKeyCode.F23,
176             SDL_SCANCODE_F24: KeyboardKeyCode.F24,
177             SDL_SCANCODE_EXECUTE: KeyboardKeyCode.EXECUTE,
178             SDL_SCANCODE_HELP: KeyboardKeyCode.HELP,
179             SDL_SCANCODE_MENU: KeyboardKeyCode.MENU,
180             SDL_SCANCODE_SELECT: KeyboardKeyCode.SELECT,
181             SDL_SCANCODE_STOP: KeyboardKeyCode.STOP,
182             SDL_SCANCODE_AGAIN: KeyboardKeyCode.AGAIN,
183             SDL_SCANCODE_UNDO: KeyboardKeyCode.UNDO,
184             SDL_SCANCODE_CUT: KeyboardKeyCode.CUT,
185             SDL_SCANCODE_COPY: KeyboardKeyCode.COPY,
186             SDL_SCANCODE_PASTE: KeyboardKeyCode.PASTE,
187             SDL_SCANCODE_FIND: KeyboardKeyCode.FIND,
188             SDL_SCANCODE_MUTE: KeyboardKeyCode.MUTE,
189             SDL_SCANCODE_VOLUMEUP: KeyboardKeyCode.VOLUMEUP,
190             SDL_SCANCODE_VOLUMEDOWN: KeyboardKeyCode.VOLUMEDOWN,
191             SDL_SCANCODE_KP_COMMA: KeyboardKeyCode.KEYPAD_COMMA,
192             SDL_SCANCODE_KP_EQUALSAS400: KeyboardKeyCode.KEYPAD_EQUALSAS400,
193 
194             SDL_SCANCODE_INTERNATIONAL1: KeyboardKeyCode.INTERNATIONAL1,
195             SDL_SCANCODE_INTERNATIONAL2: KeyboardKeyCode.INTERNATIONAL2,
196             SDL_SCANCODE_INTERNATIONAL3: KeyboardKeyCode.INTERNATIONAL3,
197             SDL_SCANCODE_INTERNATIONAL4: KeyboardKeyCode.INTERNATIONAL4,
198             SDL_SCANCODE_INTERNATIONAL5: KeyboardKeyCode.INTERNATIONAL5,
199             SDL_SCANCODE_INTERNATIONAL6: KeyboardKeyCode.INTERNATIONAL6,
200             SDL_SCANCODE_INTERNATIONAL7: KeyboardKeyCode.INTERNATIONAL7,
201             SDL_SCANCODE_INTERNATIONAL8: KeyboardKeyCode.INTERNATIONAL8,
202             SDL_SCANCODE_INTERNATIONAL9: KeyboardKeyCode.INTERNATIONAL9,
203             SDL_SCANCODE_LANG1: KeyboardKeyCode.LANG1,
204             SDL_SCANCODE_LANG2: KeyboardKeyCode.LANG2,
205             SDL_SCANCODE_LANG3: KeyboardKeyCode.LANG3,
206             SDL_SCANCODE_LANG4: KeyboardKeyCode.LANG4,
207             SDL_SCANCODE_LANG5: KeyboardKeyCode.LANG5,
208             SDL_SCANCODE_LANG6: KeyboardKeyCode.LANG6,
209             SDL_SCANCODE_LANG7: KeyboardKeyCode.LANG7,
210             SDL_SCANCODE_LANG8: KeyboardKeyCode.LANG8,
211             SDL_SCANCODE_LANG9: KeyboardKeyCode.LANG9,
212 
213             SDL_SCANCODE_ALTERASE: KeyboardKeyCode.ALTERASE,
214             SDL_SCANCODE_SYSREQ: KeyboardKeyCode.SYSREQ,
215             SDL_SCANCODE_CANCEL: KeyboardKeyCode.CANCEL,
216             SDL_SCANCODE_CLEAR: KeyboardKeyCode.CLEAR,
217             SDL_SCANCODE_PRIOR: KeyboardKeyCode.PRIOR,
218             SDL_SCANCODE_RETURN2: KeyboardKeyCode.RETURN2,
219             SDL_SCANCODE_SEPARATOR: KeyboardKeyCode.SEPARATOR,
220             SDL_SCANCODE_OUT: KeyboardKeyCode.OUT,
221             SDL_SCANCODE_OPER: KeyboardKeyCode.OPER,
222             SDL_SCANCODE_CLEARAGAIN: KeyboardKeyCode.CLEARAGAIN,
223             SDL_SCANCODE_CRSEL: KeyboardKeyCode.CRSEL,
224             SDL_SCANCODE_EXSEL: KeyboardKeyCode.EXSEL,
225 
226             SDL_SCANCODE_KP_00: KeyboardKeyCode.KEYPAD_00,
227             SDL_SCANCODE_KP_000: KeyboardKeyCode.KEYPAD_000,
228             SDL_SCANCODE_THOUSANDSSEPARATOR: KeyboardKeyCode.THOUSANDSSEPARATOR,
229             SDL_SCANCODE_DECIMALSEPARATOR: KeyboardKeyCode.DECIMALSEPARATOR,
230             SDL_SCANCODE_CURRENCYUNIT: KeyboardKeyCode.CURRENCYUNIT,
231             SDL_SCANCODE_CURRENCYSUBUNIT: KeyboardKeyCode.CURRENCYSUBUNIT,
232             SDL_SCANCODE_KP_LEFTPAREN: KeyboardKeyCode.KP_LEFTPAREN,
233             SDL_SCANCODE_KP_RIGHTPAREN: KeyboardKeyCode.KP_RIGHTPAREN,
234             SDL_SCANCODE_KP_LEFTBRACE: KeyboardKeyCode.KP_LEFTBRACE,
235             SDL_SCANCODE_KP_RIGHTBRACE: KeyboardKeyCode.KP_RIGHTBRACE,
236             SDL_SCANCODE_KP_TAB: KeyboardKeyCode.KP_TAB,
237             SDL_SCANCODE_KP_BACKSPACE: KeyboardKeyCode.KP_BACKSPACE,
238             SDL_SCANCODE_KP_A: KeyboardKeyCode.KP_A,
239             SDL_SCANCODE_KP_B: KeyboardKeyCode.KP_B,
240             SDL_SCANCODE_KP_C: KeyboardKeyCode.KP_C,
241             SDL_SCANCODE_KP_D: KeyboardKeyCode.KP_D,
242             SDL_SCANCODE_KP_E: KeyboardKeyCode.KP_E,
243             SDL_SCANCODE_KP_F: KeyboardKeyCode.KP_F,
244             SDL_SCANCODE_KP_XOR: KeyboardKeyCode.KP_XOR,
245             SDL_SCANCODE_KP_POWER: KeyboardKeyCode.KP_POWER,
246             SDL_SCANCODE_KP_PERCENT: KeyboardKeyCode.KP_PERCENT,
247             SDL_SCANCODE_KP_LESS: KeyboardKeyCode.KP_LESS,
248             SDL_SCANCODE_KP_GREATER: KeyboardKeyCode.KP_GREATER,
249             SDL_SCANCODE_KP_AMPERSAND: KeyboardKeyCode.KP_AMPERSAND,
250             SDL_SCANCODE_KP_DBLAMPERSAND: KeyboardKeyCode.KP_DBLAMPERSAND,
251             SDL_SCANCODE_KP_VERTICALBAR: KeyboardKeyCode.KP_VERTICALBAR,
252             SDL_SCANCODE_KP_DBLVERTICALBAR: KeyboardKeyCode.KP_DBLVERTICALBAR,
253             SDL_SCANCODE_KP_COLON: KeyboardKeyCode.KP_COLON,
254             SDL_SCANCODE_KP_HASH: KeyboardKeyCode.KP_HASH,
255             SDL_SCANCODE_KP_SPACE: KeyboardKeyCode.KP_SPACE,
256             SDL_SCANCODE_KP_AT: KeyboardKeyCode.KP_AT,
257             SDL_SCANCODE_KP_EXCLAM: KeyboardKeyCode.KP_EXCLAM,
258             SDL_SCANCODE_KP_MEMSTORE: KeyboardKeyCode.KP_MEMSTORE,
259             SDL_SCANCODE_KP_MEMRECALL: KeyboardKeyCode.KP_MEMRECALL,
260             SDL_SCANCODE_KP_MEMCLEAR: KeyboardKeyCode.KP_MEMCLEAR,
261             SDL_SCANCODE_KP_MEMADD: KeyboardKeyCode.KP_MEMADD,
262             SDL_SCANCODE_KP_MEMSUBTRACT: KeyboardKeyCode.KP_MEMSUBTRACT,
263             SDL_SCANCODE_KP_MEMMULTIPLY: KeyboardKeyCode.KP_MEMMULTIPLY,
264             SDL_SCANCODE_KP_MEMDIVIDE: KeyboardKeyCode.KP_MEMDIVIDE,
265             SDL_SCANCODE_KP_PLUSMINUS: KeyboardKeyCode.KP_PLUSMINUS,
266             SDL_SCANCODE_KP_CLEAR: KeyboardKeyCode.KP_CLEAR,
267             SDL_SCANCODE_KP_CLEARENTRY: KeyboardKeyCode.KP_CLEARENTRY,
268             SDL_SCANCODE_KP_BINARY: KeyboardKeyCode.KP_BINARY,
269             SDL_SCANCODE_KP_OCTAL: KeyboardKeyCode.KP_OCTAL,
270             SDL_SCANCODE_KP_DECIMAL: KeyboardKeyCode.KP_DECIMAL,
271             SDL_SCANCODE_KP_HEXADECIMAL: KeyboardKeyCode.KP_HEXADECIMAL,
272 
273             SDL_SCANCODE_LCTRL: KeyboardKeyCode.LCTRL,
274             SDL_SCANCODE_LSHIFT: KeyboardKeyCode.LSHIFT,
275             SDL_SCANCODE_LALT: KeyboardKeyCode.LALT,
276             SDL_SCANCODE_LGUI: KeyboardKeyCode.LGUI,
277             SDL_SCANCODE_RCTRL: KeyboardKeyCode.RCTRL,
278             SDL_SCANCODE_RSHIFT: KeyboardKeyCode.RSHIFT,
279             SDL_SCANCODE_RALT: KeyboardKeyCode.RALT,
280             SDL_SCANCODE_RGUI: KeyboardKeyCode.RGUI,
281 
282             SDL_SCANCODE_MODE: KeyboardKeyCode.MODE,
283 
284             SDL_SCANCODE_AUDIONEXT: KeyboardKeyCode.AUDIONEXT,
285             SDL_SCANCODE_AUDIOPREV: KeyboardKeyCode.AUDIOPREV,
286             SDL_SCANCODE_AUDIOSTOP: KeyboardKeyCode.AUDIOSTOP,
287             SDL_SCANCODE_AUDIOPLAY: KeyboardKeyCode.AUDIOPLAY,
288             SDL_SCANCODE_AUDIOMUTE: KeyboardKeyCode.AUDIOMUTE,
289             SDL_SCANCODE_MEDIASELECT: KeyboardKeyCode.MEDIASELECT,
290             SDL_SCANCODE_WWW: KeyboardKeyCode.WWW,
291             SDL_SCANCODE_MAIL: KeyboardKeyCode.MAIL,
292             SDL_SCANCODE_CALCULATOR: KeyboardKeyCode.CALCULATOR,
293             SDL_SCANCODE_COMPUTER: KeyboardKeyCode.COMPUTER,
294             SDL_SCANCODE_AC_SEARCH: KeyboardKeyCode.AC_SEARCH,
295             SDL_SCANCODE_AC_HOME: KeyboardKeyCode.AC_HOME,
296             SDL_SCANCODE_AC_BACK: KeyboardKeyCode.AC_BACK,
297             SDL_SCANCODE_AC_FORWARD: KeyboardKeyCode.AC_FORWARD,
298             SDL_SCANCODE_AC_STOP: KeyboardKeyCode.AC_STOP,
299             SDL_SCANCODE_AC_REFRESH: KeyboardKeyCode.AC_REFRESH,
300             SDL_SCANCODE_AC_BOOKMARKS: KeyboardKeyCode.AC_BOOKMARKS,
301 
302             SDL_SCANCODE_BRIGHTNESSDOWN: KeyboardKeyCode.BRIGHTNESSDOWN,
303             SDL_SCANCODE_BRIGHTNESSUP: KeyboardKeyCode.BRIGHTNESSUP,
304             SDL_SCANCODE_DISPLAYSWITCH: KeyboardKeyCode.DISPLAYSWITCH,
305             SDL_SCANCODE_KBDILLUMTOGGLE: KeyboardKeyCode.KBDILLUMTOGGLE,
306             SDL_SCANCODE_KBDILLUMDOWN: KeyboardKeyCode.KBDILLUMDOWN,
307             SDL_SCANCODE_KBDILLUMUP: KeyboardKeyCode.KBDILLUMUP,
308             SDL_SCANCODE_EJECT: KeyboardKeyCode.EJECT,
309             SDL_SCANCODE_SLEEP: KeyboardKeyCode.SLEEP,
310 
311             SDL_SCANCODE_APP1: KeyboardKeyCode.APP1,
312             SDL_SCANCODE_APP2: KeyboardKeyCode.APP2
313         ];
314 
315         mouseButtonMap = [
316             SDL_BUTTON_LEFT: MouseButton.LEFT,
317             SDL_BUTTON_MIDDLE: MouseButton.MIDDLE,
318             SDL_BUTTON_RIGHT: MouseButton.RIGHT,
319             SDL_BUTTON_X1: MouseButton.X1,
320             SDL_BUTTON_X2: MouseButton.X2
321         ];
322     }
323 
324     public override void handleEvents() {
325         SDL_Event event;
326         bool handledMouseMotionEvent = false;
327 
328         while (SDL_PollEvent(&event)) {
329             switch(event.type) {
330                 case SDL_QUIT:
331                     coreEngineCommandChannel.emit(Event(EngineCommand.quit, 1));
332                     break;
333                 case SDL_JOYAXISMOTION:
334                     handleJoystickEvents && emitJoyAxisEvent(event);
335                     break;
336                 case SDL_JOYBALLMOTION:
337                     handleJoystickEvents && emitJoyBallMotionEvent(event);
338                     break;
339                 case SDL_JOYHATMOTION:
340                     handleJoystickEvents && emitJoyHatEvent(event);
341                     break;
342                 case SDL_JOYBUTTONDOWN:
343                 case SDL_JOYBUTTONUP:
344                     handleJoystickEvents && emitJoyButtonEvent(event);
345                     break;
346                 case SDL_JOYDEVICEADDED:
347                     if (handleJoystickEvents) {
348                         inputDeviceManager.openJoystick(event.jdevice.which);
349                         emitJoyDeviceAddedEvent(event);
350                     }
351                     break;
352                 case SDL_JOYDEVICEREMOVED:
353                     if (handleJoystickEvents) {
354                         inputDeviceManager.closeJoystick(event.jdevice.which);
355                         emitJoyDeviceRemovedEvent(event);
356                     }
357                     break;
358                 case SDL_KEYDOWN:
359                 case SDL_KEYUP:
360                     handleKeyboardEvents && emitKeyboardKeyEvent(event);
361                     break;
362                 case SDL_MOUSEMOTION:
363                     if (handleMouseEvents) {
364                         handledMouseMotionEvent = true;
365                         emitMouseMotionEvent(event);
366                     }
367                     break;
368                 case SDL_MOUSEBUTTONDOWN:
369                 case SDL_MOUSEBUTTONUP:
370                     handleMouseEvents && emitMouseButtonEvent(event);
371                     break;
372                 case SDL_MOUSEWHEEL:
373                     handleMouseEvents && emitMouseWheelEvent(event);
374                     break;
375                 default:
376                     break;
377             }
378         }
379 
380         if (!handledMouseMotionEvent
381             && previouslyHandledMouseMotionEvent
382             && inputDeviceManager.captureMouse
383             && inputDeviceManager.emitMouseMotionReset) {
384             emitMouseMotionResetEvent();
385         }
386     }
387 
388     private void emitJoyAxisEvent(const ref SDL_Event event) {
389         double magnitude = cast(double) event.jaxis.value / 32767;
390         auto axisData = new JoystickAxisEventData();
391         axisData.device = Device(DeviceType.joystick, cast(int) event.jaxis.which);
392         axisData.axis = event.jaxis.axis;
393         rawInputEventChannel.emit(Event(InputEvent.JOYSTICK_AXIS_MOVEMENT, magnitude, axisData));
394     }
395 
396     private void emitJoyBallMotionEvent(const ref SDL_Event event) {
397         auto xBallData = new JoystickBallEventData();
398         auto yBallData = new JoystickBallEventData();
399         xBallData.axis = JoystickBallAxis.X;
400         yBallData.axis = JoystickBallAxis.Y;
401         xBallData.device = Device(DeviceType.joystick, cast(int) event.jball.which);
402         yBallData.device = Device(DeviceType.joystick, cast(int) event.jball.which);
403         double xBallMagnitude = cast(double) event.jball.xrel / 32767;
404         double yBallMagnitude = cast(double) event.jball.yrel / 32767;
405 
406         rawInputEventChannel.emit(Event(InputEvent.JOYSTICK_BALL_MOVEMENT, xBallMagnitude, xBallData));
407         rawInputEventChannel.emit(Event(InputEvent.JOYSTICK_BALL_MOVEMENT, yBallMagnitude, yBallData));
408     }
409 
410     private void emitJoyHatEvent(const ref SDL_Event event) {
411         auto hatData = new JoystickHatEventData();
412         hatData.device = Device(DeviceType.joystick, cast(int) event.jhat.which);
413         hatData.hat = event.jhat.hat;
414         hatData.postion = hatMap[event.jhat.value];
415         rawInputEventChannel.emit(Event(InputEvent.JOYSTICK_HAT, 1, hatData));
416     }
417 
418     private void emitJoyButtonEvent(const ref SDL_Event event) {
419         auto buttonData = new JoystickButtonEventData();
420         buttonData.device = Device(DeviceType.joystick, cast(int) event.jbutton.which);
421         buttonData.button = event.jbutton.button;
422         double magnitude = event.jbutton.state == SDL_PRESSED ? 1 : 0;
423         rawInputEventChannel.emit(Event(InputEvent.JOYSTICK_BUTTON, magnitude, buttonData));
424     }
425 
426     private void emitJoyDeviceAddedEvent(const ref SDL_Event event) {
427         auto joystickData = new InputMessageData();
428         joystickData.device = Device(DeviceType.joystick, cast(int) event.jdevice.which);
429         rawInputEventChannel.emit(Event(InputEvent.JOYSTICK_ADDED, 1, joystickData));
430     }
431 
432     private void emitJoyDeviceRemovedEvent(const ref SDL_Event event) {
433         auto joystickData = new InputMessageData();
434         joystickData.device = Device(DeviceType.joystick, cast(int) event.jdevice.which);
435         rawInputEventChannel.emit(Event(InputEvent.JOYSTICK_REMOVED, 1, joystickData));
436     }
437 
438     private void emitKeyboardKeyEvent(const ref SDL_Event event) {
439         if (event.key.repeat == 0) {
440             double magnitude = event.key.state == SDL_PRESSED ? 1 : 0;
441             auto keyboardData = new KeyboardKeyEventData();
442             keyboardData.device = Device(DeviceType.keyboard);
443             keyboardData.scanCode = scanCodeMap[event.key.keysym.scancode];
444             keyboardData.modifiers = createModifiers(event.key.keysym.mod);
445             rawInputEventChannel.emit(Event(InputEvent.KEYBOARD_KEY, magnitude, keyboardData));
446         }
447     }
448 
449     private KeyboardKeyModifier createModifiers(ushort sdlModifiers) {
450         auto modifiers = KeyboardKeyModifier.NONE;
451 
452         if (sdlModifiers & KMOD_LSHIFT) { modifiers |= KeyboardKeyModifier.LSHIFT; }
453         if (sdlModifiers & KMOD_RSHIFT) { modifiers |= KeyboardKeyModifier.RSHIFT; }
454         if (sdlModifiers & KMOD_LCTRL)  { modifiers |= KeyboardKeyModifier.LCTRL; }
455         if (sdlModifiers & KMOD_RCTRL)  { modifiers |= KeyboardKeyModifier.RCTRL; }
456         if (sdlModifiers & KMOD_LALT)   { modifiers |= KeyboardKeyModifier.LALT; }
457         if (sdlModifiers & KMOD_RALT)   { modifiers |= KeyboardKeyModifier.RALT; }
458         if (sdlModifiers & KMOD_LGUI)   { modifiers |= KeyboardKeyModifier.LGUI; }
459         if (sdlModifiers & KMOD_RGUI)   { modifiers |= KeyboardKeyModifier.RGUI; }
460         if (sdlModifiers & KMOD_NUM)    { modifiers |= KeyboardKeyModifier.NUM; }
461         if (sdlModifiers & KMOD_CAPS)   { modifiers |= KeyboardKeyModifier.CAPS; }
462         if (sdlModifiers & KMOD_MODE)   { modifiers |= KeyboardKeyModifier.MODE; }
463         if (sdlModifiers & KMOD_CTRL)   { modifiers |= KeyboardKeyModifier.CTRL; }
464         if (sdlModifiers & KMOD_SHIFT)  { modifiers |= KeyboardKeyModifier.SHIFT; }
465         if (sdlModifiers & KMOD_ALT)    { modifiers |= KeyboardKeyModifier.ALT; }
466         if (sdlModifiers & KMOD_GUI)    { modifiers |= KeyboardKeyModifier.GUI; }
467 
468         return modifiers;
469     }
470 
471     private void emitMouseMotionEvent(const ref SDL_Event event) {
472         auto xMouseMotionData = new MouseMotionEventData();
473         xMouseMotionData.device = Device(DeviceType.mouse);
474         double xMagnitude = (cast(double) event.motion.xrel / mouseMotionMax) * inputDeviceManager.mouseSensitivityModifier;
475         xMouseMotionData.axis = MouseAxis.X;
476         xMouseMotionData.absolutePosition = event.motion.x;
477 
478         auto yMouseMotionData = new MouseMotionEventData();
479         yMouseMotionData.device = Device(DeviceType.mouse);
480         double yMagnitude = (cast(double) event.motion.yrel / mouseMotionMax) * inputDeviceManager.mouseSensitivityModifier;
481         yMouseMotionData.axis = MouseAxis.Y;
482         yMouseMotionData.absolutePosition = event.motion.y;
483 
484         rawInputEventChannel.emit(Event(InputEvent.MOUSE_MOTION, xMagnitude, xMouseMotionData));
485         rawInputEventChannel.emit(Event(InputEvent.MOUSE_MOTION, yMagnitude, yMouseMotionData));
486 
487         previouslyHandledMouseMotionEvent = true;
488     }
489 
490     private void emitMouseMotionResetEvent() {
491         auto xMouseMotionData = new MouseMotionEventData();
492         xMouseMotionData.device = Device(DeviceType.mouse);
493         xMouseMotionData.axis = MouseAxis.X;
494 
495         auto yMouseMotionData = new MouseMotionEventData();
496         yMouseMotionData.device = Device(DeviceType.mouse);
497         yMouseMotionData.axis = MouseAxis.Y;
498 
499         rawInputEventChannel.emit(Event(InputEvent.MOUSE_MOTION, 0, xMouseMotionData));
500         rawInputEventChannel.emit(Event(InputEvent.MOUSE_MOTION, 0, yMouseMotionData));
501 
502         previouslyHandledMouseMotionEvent = false;
503     }
504 
505     private void emitMouseButtonEvent(const ref SDL_Event event) {
506         auto mouseButtonData = new MouseButtonEventData();
507         mouseButtonData.device = Device(DeviceType.mouse);
508         double magnitude = event.button.state == SDL_PRESSED ? 1 : 0;
509         mouseButtonData.button = mouseButtonMap[event.button.button];
510 
511         rawInputEventChannel.emit(Event(InputEvent.MOUSE_BUTTON, magnitude, mouseButtonData));
512     }
513 
514     private void emitMouseWheelEvent(const ref SDL_Event event) {
515         double magnitude = event.wheel.y;
516 
517         if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
518             magnitude *= -1;
519         }
520 
521         auto mouseWheelEventData = new InputMessageData();
522         mouseWheelEventData.device = Device(DeviceType.mouse);
523 
524         rawInputEventChannel.emit(Event(InputEvent.MOUSE_WHEEL, magnitude, mouseWheelEventData));
525     }
526 }
527 
528 }