1 /*
2  * ============================================================================
3  *  Title:    Event Handling Driver for SDL2
4  *  Author:   J. Zbiciak
5  * ============================================================================
6  *  This is the platform-specific driver for SDL 1.x.
7  * ============================================================================
8  */
9 
10 #include "config.h"
11 #include "sdl_jzintv.h"
12 #include "event/event_tbl.h"
13 #include "event/event_plat.h"
14 #include "event/event_sdl_pvt.h"
15 
16 #define REMAP(x) (((x) & 0x1FF) | ((x) & (1ul << 30) ? 0x200 : 0))
17 
18 /* ======================================================================== */
19 /*  SDK_KEYMAP   -- Maps SDLK values to EVENT values.                       */
20 /* ======================================================================== */
21 static const event_num_t sdl_keymap[] =
22 {
23     [REMAP(SDLK_UNKNOWN)]               = EVENT_UNKNOWN,
24     [REMAP(SDLK_BACKSPACE)]             = EVENT_BACKSPACE,
25     [REMAP(SDLK_TAB)]                   = EVENT_TAB,
26     [REMAP(SDLK_CLEAR)]                 = EVENT_CLEAR,
27     [REMAP(SDLK_RETURN)]                = EVENT_RETURN,
28     [REMAP(SDLK_PAUSE)]                 = EVENT_PAUSE,
29     [REMAP(SDLK_ESCAPE)]                = EVENT_ESCAPE,
30     [REMAP(SDLK_SPACE)]                 = EVENT_SPACE,
31     [REMAP(SDLK_EXCLAIM)]               = EVENT_EXCLAIM,
32     [REMAP(SDLK_QUOTEDBL)]              = EVENT_QUOTEDBL,
33     [REMAP(SDLK_HASH)]                  = EVENT_HASH,
34     [REMAP(SDLK_DOLLAR)]                = EVENT_DOLLAR,
35     [REMAP(SDLK_AMPERSAND)]             = EVENT_AMPERSAND,
36     [REMAP(SDLK_QUOTE)]                 = EVENT_QUOTE,
37     [REMAP(SDLK_LEFTPAREN)]             = EVENT_LEFTPAREN,
38     [REMAP(SDLK_RIGHTPAREN)]            = EVENT_RIGHTPAREN,
39     [REMAP(SDLK_ASTERISK)]              = EVENT_ASTERISK,
40     [REMAP(SDLK_PLUS)]                  = EVENT_PLUS,
41     [REMAP(SDLK_COMMA)]                 = EVENT_COMMA,
42     [REMAP(SDLK_MINUS)]                 = EVENT_MINUS,
43     [REMAP(SDLK_PERIOD)]                = EVENT_PERIOD,
44     [REMAP(SDLK_SLASH)]                 = EVENT_SLASH,
45     [REMAP(SDLK_0)]                     = EVENT_0,
46     [REMAP(SDLK_1)]                     = EVENT_1,
47     [REMAP(SDLK_2)]                     = EVENT_2,
48     [REMAP(SDLK_3)]                     = EVENT_3,
49     [REMAP(SDLK_4)]                     = EVENT_4,
50     [REMAP(SDLK_5)]                     = EVENT_5,
51     [REMAP(SDLK_6)]                     = EVENT_6,
52     [REMAP(SDLK_7)]                     = EVENT_7,
53     [REMAP(SDLK_8)]                     = EVENT_8,
54     [REMAP(SDLK_9)]                     = EVENT_9,
55     [REMAP(SDLK_COLON)]                 = EVENT_COLON,
56     [REMAP(SDLK_SEMICOLON)]             = EVENT_SEMICOLON,
57     [REMAP(SDLK_LESS)]                  = EVENT_LESS,
58     [REMAP(SDLK_EQUALS)]                = EVENT_EQUALS,
59     [REMAP(SDLK_GREATER)]               = EVENT_GREATER,
60     [REMAP(SDLK_QUESTION)]              = EVENT_QUESTION,
61     [REMAP(SDLK_AT)]                    = EVENT_AT,
62     [REMAP(SDLK_LEFTBRACKET)]           = EVENT_LEFTBRACKET,
63     [REMAP(SDLK_BACKSLASH)]             = EVENT_BACKSLASH,
64     [REMAP(SDLK_RIGHTBRACKET)]          = EVENT_RIGHTBRACKET,
65     [REMAP(SDLK_CARET)]                 = EVENT_CARET,
66     [REMAP(SDLK_UNDERSCORE)]            = EVENT_UNDERSCORE,
67     [REMAP(SDLK_BACKQUOTE)]             = EVENT_BACKQUOTE,
68     [REMAP(SDLK_a)]                     = EVENT_A,
69     [REMAP(SDLK_b)]                     = EVENT_B,
70     [REMAP(SDLK_c)]                     = EVENT_C,
71     [REMAP(SDLK_d)]                     = EVENT_D,
72     [REMAP(SDLK_e)]                     = EVENT_E,
73     [REMAP(SDLK_f)]                     = EVENT_F,
74     [REMAP(SDLK_g)]                     = EVENT_G,
75     [REMAP(SDLK_h)]                     = EVENT_H,
76     [REMAP(SDLK_i)]                     = EVENT_I,
77     [REMAP(SDLK_j)]                     = EVENT_J,
78     [REMAP(SDLK_k)]                     = EVENT_K,
79     [REMAP(SDLK_l)]                     = EVENT_L,
80     [REMAP(SDLK_m)]                     = EVENT_M,
81     [REMAP(SDLK_n)]                     = EVENT_N,
82     [REMAP(SDLK_o)]                     = EVENT_O,
83     [REMAP(SDLK_p)]                     = EVENT_P,
84     [REMAP(SDLK_q)]                     = EVENT_Q,
85     [REMAP(SDLK_r)]                     = EVENT_R,
86     [REMAP(SDLK_s)]                     = EVENT_S,
87     [REMAP(SDLK_t)]                     = EVENT_T,
88     [REMAP(SDLK_u)]                     = EVENT_U,
89     [REMAP(SDLK_v)]                     = EVENT_V,
90     [REMAP(SDLK_w)]                     = EVENT_W,
91     [REMAP(SDLK_x)]                     = EVENT_X,
92     [REMAP(SDLK_y)]                     = EVENT_Y,
93     [REMAP(SDLK_z)]                     = EVENT_Z,
94     [REMAP(SDLK_DELETE)]                = EVENT_DELETE,
95     [REMAP(SDLK_KP_0)]                  = EVENT_KP_0,
96     [REMAP(SDLK_KP_1)]                  = EVENT_KP_1,
97     [REMAP(SDLK_KP_2)]                  = EVENT_KP_2,
98     [REMAP(SDLK_KP_3)]                  = EVENT_KP_3,
99     [REMAP(SDLK_KP_4)]                  = EVENT_KP_4,
100     [REMAP(SDLK_KP_5)]                  = EVENT_KP_5,
101     [REMAP(SDLK_KP_6)]                  = EVENT_KP_6,
102     [REMAP(SDLK_KP_7)]                  = EVENT_KP_7,
103     [REMAP(SDLK_KP_8)]                  = EVENT_KP_8,
104     [REMAP(SDLK_KP_9)]                  = EVENT_KP_9,
105     [REMAP(SDLK_KP_PERIOD)]             = EVENT_KP_PERIOD,
106     [REMAP(SDLK_KP_DIVIDE)]             = EVENT_KP_DIVIDE,
107     [REMAP(SDLK_KP_MULTIPLY)]           = EVENT_KP_MULTIPLY,
108     [REMAP(SDLK_KP_MINUS)]              = EVENT_KP_MINUS,
109     [REMAP(SDLK_KP_PLUS)]               = EVENT_KP_PLUS,
110     [REMAP(SDLK_KP_ENTER)]              = EVENT_KP_ENTER,
111     [REMAP(SDLK_KP_EQUALS)]             = EVENT_KP_EQUALS,
112     [REMAP(SDLK_UP)]                    = EVENT_UP,
113     [REMAP(SDLK_DOWN)]                  = EVENT_DOWN,
114     [REMAP(SDLK_RIGHT)]                 = EVENT_RIGHT,
115     [REMAP(SDLK_LEFT)]                  = EVENT_LEFT,
116     [REMAP(SDLK_INSERT)]                = EVENT_INSERT,
117     [REMAP(SDLK_HOME)]                  = EVENT_HOME,
118     [REMAP(SDLK_END)]                   = EVENT_END,
119     [REMAP(SDLK_PAGEUP)]                = EVENT_PAGEUP,
120     [REMAP(SDLK_PAGEDOWN)]              = EVENT_PAGEDOWN,
121     [REMAP(SDLK_F1)]                    = EVENT_F1,
122     [REMAP(SDLK_F2)]                    = EVENT_F2,
123     [REMAP(SDLK_F3)]                    = EVENT_F3,
124     [REMAP(SDLK_F4)]                    = EVENT_F4,
125     [REMAP(SDLK_F5)]                    = EVENT_F5,
126     [REMAP(SDLK_F6)]                    = EVENT_F6,
127     [REMAP(SDLK_F7)]                    = EVENT_F7,
128     [REMAP(SDLK_F8)]                    = EVENT_F8,
129     [REMAP(SDLK_F9)]                    = EVENT_F9,
130     [REMAP(SDLK_F10)]                   = EVENT_F10,
131     [REMAP(SDLK_F11)]                   = EVENT_F11,
132     [REMAP(SDLK_F12)]                   = EVENT_F12,
133     [REMAP(SDLK_F13)]                   = EVENT_F13,
134     [REMAP(SDLK_F14)]                   = EVENT_F14,
135     [REMAP(SDLK_F15)]                   = EVENT_F15,
136     [REMAP(SDLK_NUMLOCKCLEAR)]          = EVENT_NUMLOCK,
137     [REMAP(SDLK_CAPSLOCK)]              = EVENT_CAPSLOCK,
138     [REMAP(SDLK_SCROLLLOCK)]            = EVENT_SCROLLOCK,
139     [REMAP(SDLK_RSHIFT)]                = EVENT_RSHIFT,
140     [REMAP(SDLK_LSHIFT)]                = EVENT_LSHIFT,
141     [REMAP(SDLK_RCTRL)]                 = EVENT_RCTRL,
142     [REMAP(SDLK_LCTRL)]                 = EVENT_LCTRL,
143     [REMAP(SDLK_RALT)]                  = EVENT_RALT,
144     [REMAP(SDLK_LALT)]                  = EVENT_LALT,
145     [REMAP(SDLK_MODE)]                  = EVENT_MODE,
146     [REMAP(SDLK_HELP)]                  = EVENT_HELP,
147     [REMAP(SDLK_PRINTSCREEN)]           = EVENT_PRINT,
148     [REMAP(SDLK_SYSREQ)]                = EVENT_SYSREQ,
149     [REMAP(SDLK_MENU)]                  = EVENT_MENU,
150     [REMAP(SDLK_POWER)]                 = EVENT_POWER,
151     [REMAP(SDLK_UNDO)]                  = EVENT_UNDO,
152 
153     /* New for SDL2 */
154     [REMAP(SDLK_LGUI)]                  = EVENT_LGUI,
155     [REMAP(SDLK_RGUI)]                  = EVENT_RGUI,
156     [REMAP(SDLK_F16)]                   = EVENT_F16,
157     [REMAP(SDLK_F17)]                   = EVENT_F17,
158     [REMAP(SDLK_F18)]                   = EVENT_F18,
159     [REMAP(SDLK_F19)]                   = EVENT_F19,
160     [REMAP(SDLK_F20)]                   = EVENT_F20,
161     [REMAP(SDLK_F21)]                   = EVENT_F21,
162     [REMAP(SDLK_F22)]                   = EVENT_F22,
163     [REMAP(SDLK_F23)]                   = EVENT_F23,
164     [REMAP(SDLK_F24)]                   = EVENT_F24,
165     [REMAP(SDLK_SELECT)]                = EVENT_SELECT,
166     [REMAP(SDLK_STOP)]                  = EVENT_STOP,
167     [REMAP(SDLK_AGAIN)]                 = EVENT_AGAIN,
168     [REMAP(SDLK_CUT)]                   = EVENT_CUT,
169     [REMAP(SDLK_COPY)]                  = EVENT_COPY,
170     [REMAP(SDLK_PASTE)]                 = EVENT_PASTE,
171     [REMAP(SDLK_FIND)]                  = EVENT_FIND,
172     [REMAP(SDLK_MUTE)]                  = EVENT_MUTE,
173     [REMAP(SDLK_VOLUMEUP)]              = EVENT_VOLUMEUP,
174     [REMAP(SDLK_VOLUMEDOWN)]            = EVENT_VOLUMEDOWN,
175     [REMAP(SDLK_KP_COMMA)]              = EVENT_KP_COMMA,
176     [REMAP(SDLK_KP_000)]                = EVENT_KP_000,
177     [REMAP(SDLK_KP_00)]                 = EVENT_KP_00,
178     [REMAP(SDLK_KP_EQUALSAS400)]        = EVENT_KP_EQUALSAS400,
179     [REMAP(SDLK_CANCEL)]                = EVENT_CANCEL,
180     [REMAP(SDLK_PRIOR)]                 = EVENT_PRIOR,
181     [REMAP(SDLK_SEPARATOR)]             = EVENT_SEPARATOR,
182     [REMAP(SDLK_OUT)]                   = EVENT_OUT,
183     [REMAP(SDLK_OPER)]                  = EVENT_OPER,
184     [REMAP(SDLK_CLEARAGAIN)]            = EVENT_CLEARAGAIN,
185     [REMAP(SDLK_CRSEL)]                 = EVENT_CRSEL,
186     [REMAP(SDLK_EXSEL)]                 = EVENT_EXSEL,
187     [REMAP(SDLK_THOUSANDSSEPARATOR)]    = EVENT_THOUSANDSSEPARATOR,
188     [REMAP(SDLK_DECIMALSEPARATOR)]      = EVENT_DECIMALSEPARATOR,
189     [REMAP(SDLK_CURRENCYUNIT)]          = EVENT_CURRENCYUNIT,
190     [REMAP(SDLK_CURRENCYSUBUNIT)]       = EVENT_CURRENCYSUBUNIT,
191     [REMAP(SDLK_KP_LEFTPAREN)]          = EVENT_KP_LEFTPAREN,
192     [REMAP(SDLK_KP_RIGHTPAREN)]         = EVENT_KP_RIGHTPAREN,
193     [REMAP(SDLK_KP_LEFTBRACE)]          = EVENT_KP_LEFTBRACE,
194     [REMAP(SDLK_KP_RIGHTBRACE)]         = EVENT_KP_RIGHTBRACE,
195     [REMAP(SDLK_KP_TAB)]                = EVENT_KP_TAB,
196     [REMAP(SDLK_KP_BACKSPACE)]          = EVENT_KP_BACKSPACE,
197     [REMAP(SDLK_KP_A)]                  = EVENT_KP_A,
198     [REMAP(SDLK_KP_B)]                  = EVENT_KP_B,
199     [REMAP(SDLK_KP_C)]                  = EVENT_KP_C,
200     [REMAP(SDLK_KP_D)]                  = EVENT_KP_D,
201     [REMAP(SDLK_KP_E)]                  = EVENT_KP_E,
202     [REMAP(SDLK_KP_F)]                  = EVENT_KP_F,
203     [REMAP(SDLK_KP_XOR)]                = EVENT_KP_XOR,
204     [REMAP(SDLK_KP_POWER)]              = EVENT_KP_POWER,
205     [REMAP(SDLK_KP_PERCENT)]            = EVENT_KP_PERCENT,
206     [REMAP(SDLK_KP_LESS)]               = EVENT_KP_LESS,
207     [REMAP(SDLK_KP_GREATER)]            = EVENT_KP_GREATER,
208     [REMAP(SDLK_KP_AMPERSAND)]          = EVENT_KP_AMPERSAND,
209     [REMAP(SDLK_KP_DBLAMPERSAND)]       = EVENT_KP_DBLAMPERSAND,
210     [REMAP(SDLK_KP_VERTICALBAR)]        = EVENT_KP_VERTICALBAR,
211     [REMAP(SDLK_KP_DBLVERTICALBAR)]     = EVENT_KP_DBLVERTICALBAR,
212     [REMAP(SDLK_KP_COLON)]              = EVENT_KP_COLON,
213     [REMAP(SDLK_KP_HASH)]               = EVENT_KP_HASH,
214     [REMAP(SDLK_KP_SPACE)]              = EVENT_KP_SPACE,
215     [REMAP(SDLK_KP_AT)]                 = EVENT_KP_AT,
216     [REMAP(SDLK_KP_EXCLAM)]             = EVENT_KP_EXCLAIM,
217     [REMAP(SDLK_KP_MEMSTORE)]           = EVENT_KP_MEMSTORE,
218     [REMAP(SDLK_KP_MEMRECALL)]          = EVENT_KP_MEMRECALL,
219     [REMAP(SDLK_KP_MEMCLEAR)]           = EVENT_KP_MEMCLEAR,
220     [REMAP(SDLK_KP_MEMADD)]             = EVENT_KP_MEMADD,
221     [REMAP(SDLK_KP_MEMSUBTRACT)]        = EVENT_KP_MEMSUBTRACT,
222     [REMAP(SDLK_KP_MEMMULTIPLY)]        = EVENT_KP_MEMMULTIPLY,
223     [REMAP(SDLK_KP_MEMDIVIDE)]          = EVENT_KP_MEMDIVIDE,
224     [REMAP(SDLK_KP_PLUSMINUS)]          = EVENT_KP_PLUSMINUS,
225     [REMAP(SDLK_KP_CLEAR)]              = EVENT_KP_CLEAR,
226     [REMAP(SDLK_KP_CLEARENTRY)]         = EVENT_KP_CLEARENTRY,
227     [REMAP(SDLK_KP_BINARY)]             = EVENT_KP_BINARY,
228     [REMAP(SDLK_KP_OCTAL)]              = EVENT_KP_OCTAL,
229     [REMAP(SDLK_KP_DECIMAL)]            = EVENT_KP_DECIMAL,
230     [REMAP(SDLK_KP_HEXADECIMAL)]        = EVENT_KP_HEXADECIMAL,
231     [REMAP(SDLK_AUDIONEXT)]             = EVENT_AUDIONEXT,
232     [REMAP(SDLK_AUDIOPREV)]             = EVENT_AUDIOPREV,
233     [REMAP(SDLK_AUDIOSTOP)]             = EVENT_AUDIOSTOP,
234     [REMAP(SDLK_AUDIOPLAY)]             = EVENT_AUDIOPLAY,
235     [REMAP(SDLK_AUDIOMUTE)]             = EVENT_AUDIOMUTE,
236     [REMAP(SDLK_MEDIASELECT)]           = EVENT_MEDIASELECT,
237     [REMAP(SDLK_WWW)]                   = EVENT_WWW,
238     [REMAP(SDLK_MAIL)]                  = EVENT_MAIL,
239     [REMAP(SDLK_CALCULATOR)]            = EVENT_CALCULATOR,
240     [REMAP(SDLK_COMPUTER)]              = EVENT_COMPUTER,
241     [REMAP(SDLK_AC_SEARCH)]             = EVENT_AC_SEARCH,
242     [REMAP(SDLK_AC_HOME)]               = EVENT_AC_HOME,
243     [REMAP(SDLK_AC_BACK)]               = EVENT_AC_BACK,
244     [REMAP(SDLK_AC_FORWARD)]            = EVENT_AC_FORWARD,
245     [REMAP(SDLK_AC_STOP)]               = EVENT_AC_STOP,
246     [REMAP(SDLK_AC_REFRESH)]            = EVENT_AC_REFRESH,
247     [REMAP(SDLK_AC_BOOKMARKS)]          = EVENT_AC_BOOKMARKS,
248     [REMAP(SDLK_BRIGHTNESSDOWN)]        = EVENT_BRIGHTNESSDOWN,
249     [REMAP(SDLK_BRIGHTNESSUP)]          = EVENT_BRIGHTNESSUP,
250     [REMAP(SDLK_DISPLAYSWITCH)]         = EVENT_DISPLAYSWITCH,
251     [REMAP(SDLK_KBDILLUMTOGGLE)]        = EVENT_KBDILLUMTOGGLE,
252     [REMAP(SDLK_KBDILLUMDOWN)]          = EVENT_KBDILLUMDOWN,
253     [REMAP(SDLK_KBDILLUMUP)]            = EVENT_KBDILLUMUP,
254     [REMAP(SDLK_EJECT)]                 = EVENT_EJECT,
255     [REMAP(SDLK_SLEEP)]                 = EVENT_SLEEP,
256 };
257 
258 static const int sdl_keymap_size = sizeof(sdl_keymap) / sizeof(sdl_keymap[0]);
259 
260 /* ======================================================================== */
261 /*  EVENT_SDL_TRANSLATE_KEY  -- Translate an SDLKey to event_num_t.         */
262 /* ======================================================================== */
event_sdl_translate_key(const SDL_Event * const event)263 event_num_t event_sdl_translate_key(const SDL_Event *const event)
264 {
265     const int remapped_key = REMAP(event->key.keysym.sym);
266     const event_num_t primary =
267         remapped_key < sdl_keymap_size ? sdl_keymap[remapped_key]
268                                        : EVENT_UNKNOWN;
269     if (primary != EVENT_UNKNOWN)
270         return primary;
271 
272     if (event->key.keysym.scancode < 0x200)
273         return EVENT_NUM_OFS(EVENT_SCANCODE_000, event->key.keysym.scancode);
274 
275     return EVENT_UNKNOWN;
276 }
277 
278 /* ======================================================================== */
279 /*  EVENT_SDL_UNHANDLED_EVENT -- Hook for SDL-version specific events.      */
280 /*  Returns true if the event ended up queuing a COMBO, false otherwise.    */
281 /* ======================================================================== */
event_sdl_unhandled_event(evt_pvt_t * const evt_pvt,const SDL_Event * const event)282 bool event_sdl_unhandled_event(evt_pvt_t *const evt_pvt,
283                                const SDL_Event *const event)
284 {
285     switch (event->type)
286     {
287         /* ---------------------------------------------------------------- */
288         /*  Window events:  Only look at whether we're iconified or not,    */
289         /*  and convert it to an up/down event on EVENT_HIDE.               */
290         /* ---------------------------------------------------------------- */
291         case SDL_WINDOWEVENT:
292         {
293             switch (event->window.event)
294             {
295                 case SDL_WINDOWEVENT_MINIMIZED:
296                     event_enqueue(evt_pvt, EV_DOWN, EVENT_HIDE);
297                     break;
298 
299                 case SDL_WINDOWEVENT_RESTORED:
300                 case SDL_WINDOWEVENT_MAXIMIZED:
301                 case SDL_WINDOWEVENT_SHOWN:
302                     event_enqueue(evt_pvt, EV_UP, EVENT_HIDE);
303                     break;
304 
305                 case SDL_WINDOWEVENT_FOCUS_GAINED:
306                     event_enqueue(evt_pvt, EV_DOWN, EVENT_FOCUS_GAINED);
307                     event_enqueue(evt_pvt, EV_UP,   EVENT_FOCUS_GAINED);
308                     break;
309 
310                 case SDL_WINDOWEVENT_FOCUS_LOST:
311                     event_enqueue(evt_pvt, EV_DOWN, EVENT_FOCUS_LOST);
312                     event_enqueue(evt_pvt, EV_UP,   EVENT_FOCUS_LOST);
313                     break;
314 
315                 default:
316                     break;
317             }
318             break;
319         }
320         default:
321             break;
322     }
323     return false;
324 }
325 
326 /* ======================================================================== */
327 /*  This program is free software; you can redistribute it and/or modify    */
328 /*  it under the terms of the GNU General Public License as published by    */
329 /*  the Free Software Foundation; either version 2 of the License, or       */
330 /*  (at your option) any later version.                                     */
331 /*                                                                          */
332 /*  This program is distributed in the hope that it will be useful,         */
333 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
334 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       */
335 /*  General Public License for more details.                                */
336 /*                                                                          */
337 /*  You should have received a copy of the GNU General Public License along */
338 /*  with this program; if not, write to the Free Software Foundation, Inc., */
339 /*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.             */
340 /* ======================================================================== */
341 /*                 Copyright (c) 2020-+Inf, Joseph Zbiciak                  */
342 /* ======================================================================== */
343