summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/events
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/events')
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_categories.c249
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_categories_c.h70
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_clipboardevents.c57
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_clipboardevents_c.h28
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_displayevents.c64
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_displayevents_c.h28
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_dropevents.c115
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_dropevents_c.h31
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_events.c1987
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_events_c.h66
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_eventwatch.c143
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_eventwatch_c.h45
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_keyboard.c922
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_keyboard_c.h87
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_keymap.c1153
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_keymap_c.h35
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_keysym_to_keycode.c68
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_keysym_to_keycode_c.h28
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_keysym_to_scancode.c439
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_keysym_to_scancode_c.h28
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_mouse.c1673
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_mouse_c.h208
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_pen.c577
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_pen_c.h99
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_quit.c194
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_scancode_tables.c71
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_scancode_tables_c.h33
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_touch.c500
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_touch_c.h60
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_windowevents.c300
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_windowevents_c.h39
-rw-r--r--contrib/SDL-3.2.8/src/events/blank_cursor.h31
-rw-r--r--contrib/SDL-3.2.8/src/events/default_cursor.h113
-rw-r--r--contrib/SDL-3.2.8/src/events/imKStoUCS.c349
-rw-r--r--contrib/SDL-3.2.8/src/events/imKStoUCS.h32
-rw-r--r--contrib/SDL-3.2.8/src/events/scancodes_darwin.h159
-rw-r--r--contrib/SDL-3.2.8/src/events/scancodes_linux.h848
-rw-r--r--contrib/SDL-3.2.8/src/events/scancodes_windows.h286
-rw-r--r--contrib/SDL-3.2.8/src/events/scancodes_xfree86.h520
39 files changed, 11735 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/events/SDL_categories.c b/contrib/SDL-3.2.8/src/events/SDL_categories.c
new file mode 100644
index 0000000..cb41f6f
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_categories.c
@@ -0,0 +1,249 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// SDL event categories
24
25#include "SDL_events_c.h"
26#include "SDL_categories_c.h"
27
28SDL_EventCategory SDL_GetEventCategory(Uint32 type)
29{
30 if (type >= SDL_EVENT_USER && type <= SDL_EVENT_LAST) {
31 return SDL_EVENTCATEGORY_USER;
32 }
33 else if (type >= SDL_EVENT_DISPLAY_FIRST && type <= SDL_EVENT_DISPLAY_LAST) {
34 return SDL_EVENTCATEGORY_DISPLAY;
35 }
36 else if (type >= SDL_EVENT_WINDOW_FIRST && type <= SDL_EVENT_WINDOW_LAST) {
37 return SDL_EVENTCATEGORY_WINDOW;
38 }
39 switch (type) {
40 default:
41 SDL_SetError("Unknown event type");
42 return SDL_EVENTCATEGORY_UNKNOWN;
43
44 case SDL_EVENT_KEYMAP_CHANGED:
45 case SDL_EVENT_TERMINATING:
46 case SDL_EVENT_LOW_MEMORY:
47 case SDL_EVENT_WILL_ENTER_BACKGROUND:
48 case SDL_EVENT_DID_ENTER_BACKGROUND:
49 case SDL_EVENT_WILL_ENTER_FOREGROUND:
50 case SDL_EVENT_DID_ENTER_FOREGROUND:
51 case SDL_EVENT_LOCALE_CHANGED:
52 case SDL_EVENT_SYSTEM_THEME_CHANGED:
53 return SDL_EVENTCATEGORY_SYSTEM;
54
55 case SDL_EVENT_RENDER_TARGETS_RESET:
56 case SDL_EVENT_RENDER_DEVICE_RESET:
57 case SDL_EVENT_RENDER_DEVICE_LOST:
58 return SDL_EVENTCATEGORY_RENDER;
59
60 case SDL_EVENT_QUIT:
61 return SDL_EVENTCATEGORY_QUIT;
62
63 case SDL_EVENT_KEY_DOWN:
64 case SDL_EVENT_KEY_UP:
65 return SDL_EVENTCATEGORY_KEY;
66
67 case SDL_EVENT_TEXT_EDITING:
68 return SDL_EVENTCATEGORY_EDIT;
69
70 case SDL_EVENT_TEXT_INPUT:
71 return SDL_EVENTCATEGORY_TEXT;
72
73 case SDL_EVENT_KEYBOARD_ADDED:
74 case SDL_EVENT_KEYBOARD_REMOVED:
75 return SDL_EVENTCATEGORY_KDEVICE;
76
77 case SDL_EVENT_TEXT_EDITING_CANDIDATES:
78 return SDL_EVENTCATEGORY_EDIT_CANDIDATES;
79
80 case SDL_EVENT_MOUSE_MOTION:
81 return SDL_EVENTCATEGORY_MOTION;
82
83 case SDL_EVENT_MOUSE_BUTTON_DOWN:
84 case SDL_EVENT_MOUSE_BUTTON_UP:
85 return SDL_EVENTCATEGORY_BUTTON;
86
87 case SDL_EVENT_MOUSE_WHEEL:
88 return SDL_EVENTCATEGORY_WHEEL;
89
90 case SDL_EVENT_MOUSE_ADDED:
91 case SDL_EVENT_MOUSE_REMOVED:
92 return SDL_EVENTCATEGORY_MDEVICE;
93
94 case SDL_EVENT_JOYSTICK_AXIS_MOTION:
95 return SDL_EVENTCATEGORY_JAXIS;
96
97 case SDL_EVENT_JOYSTICK_BALL_MOTION:
98 return SDL_EVENTCATEGORY_JBALL;
99
100 case SDL_EVENT_JOYSTICK_HAT_MOTION:
101 return SDL_EVENTCATEGORY_JHAT;
102
103 case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
104 case SDL_EVENT_JOYSTICK_BUTTON_UP:
105 return SDL_EVENTCATEGORY_JBUTTON;
106
107 case SDL_EVENT_JOYSTICK_ADDED:
108 case SDL_EVENT_JOYSTICK_REMOVED:
109 case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE:
110 return SDL_EVENTCATEGORY_JDEVICE;
111
112 case SDL_EVENT_JOYSTICK_BATTERY_UPDATED:
113 return SDL_EVENTCATEGORY_JBATTERY;
114
115 case SDL_EVENT_GAMEPAD_AXIS_MOTION:
116 return SDL_EVENTCATEGORY_GAXIS;
117
118 case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
119 case SDL_EVENT_GAMEPAD_BUTTON_UP:
120 return SDL_EVENTCATEGORY_GBUTTON;
121
122 case SDL_EVENT_GAMEPAD_ADDED:
123 case SDL_EVENT_GAMEPAD_REMOVED:
124 case SDL_EVENT_GAMEPAD_REMAPPED:
125 case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE:
126 case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED:
127 return SDL_EVENTCATEGORY_GDEVICE;
128
129 case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
130 case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
131 case SDL_EVENT_GAMEPAD_TOUCHPAD_UP:
132 return SDL_EVENTCATEGORY_GTOUCHPAD;
133
134 case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
135 return SDL_EVENTCATEGORY_GSENSOR;
136
137 case SDL_EVENT_FINGER_DOWN:
138 case SDL_EVENT_FINGER_UP:
139 case SDL_EVENT_FINGER_CANCELED:
140 case SDL_EVENT_FINGER_MOTION:
141 return SDL_EVENTCATEGORY_TFINGER;
142
143 case SDL_EVENT_CLIPBOARD_UPDATE:
144 return SDL_EVENTCATEGORY_CLIPBOARD;
145
146 case SDL_EVENT_DROP_FILE:
147 case SDL_EVENT_DROP_TEXT:
148 case SDL_EVENT_DROP_BEGIN:
149 case SDL_EVENT_DROP_COMPLETE:
150 case SDL_EVENT_DROP_POSITION:
151 return SDL_EVENTCATEGORY_DROP;
152
153 case SDL_EVENT_AUDIO_DEVICE_ADDED:
154 case SDL_EVENT_AUDIO_DEVICE_REMOVED:
155 case SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED:
156 return SDL_EVENTCATEGORY_ADEVICE;
157
158 case SDL_EVENT_SENSOR_UPDATE:
159 return SDL_EVENTCATEGORY_SENSOR;
160
161 case SDL_EVENT_PEN_PROXIMITY_IN:
162 case SDL_EVENT_PEN_PROXIMITY_OUT:
163 return SDL_EVENTCATEGORY_PPROXIMITY;
164
165 case SDL_EVENT_PEN_DOWN:
166 case SDL_EVENT_PEN_UP:
167 return SDL_EVENTCATEGORY_PTOUCH;
168
169 case SDL_EVENT_PEN_BUTTON_DOWN:
170 case SDL_EVENT_PEN_BUTTON_UP:
171 return SDL_EVENTCATEGORY_PBUTTON;
172
173 case SDL_EVENT_PEN_MOTION:
174 return SDL_EVENTCATEGORY_PMOTION;
175
176 case SDL_EVENT_PEN_AXIS:
177 return SDL_EVENTCATEGORY_PAXIS;
178
179 case SDL_EVENT_CAMERA_DEVICE_ADDED:
180 case SDL_EVENT_CAMERA_DEVICE_REMOVED:
181 case SDL_EVENT_CAMERA_DEVICE_APPROVED:
182 case SDL_EVENT_CAMERA_DEVICE_DENIED:
183 return SDL_EVENTCATEGORY_CDEVICE;
184 }
185}
186
187SDL_Window *SDL_GetWindowFromEvent(const SDL_Event *event)
188{
189 SDL_WindowID windowID;
190
191 switch (SDL_GetEventCategory(event->type)) {
192 case SDL_EVENTCATEGORY_USER:
193 windowID = event->user.windowID;
194 break;
195 case SDL_EVENTCATEGORY_WINDOW:
196 windowID = event->window.windowID;
197 break;
198 case SDL_EVENTCATEGORY_KEY:
199 windowID = event->key.windowID;
200 break;
201 case SDL_EVENTCATEGORY_EDIT:
202 windowID = event->edit.windowID;
203 break;
204 case SDL_EVENTCATEGORY_TEXT:
205 windowID = event->text.windowID;
206 break;
207 case SDL_EVENTCATEGORY_EDIT_CANDIDATES:
208 windowID = event->edit_candidates.windowID;
209 break;
210 case SDL_EVENTCATEGORY_MOTION:
211 windowID = event->motion.windowID;
212 break;
213 case SDL_EVENTCATEGORY_BUTTON:
214 windowID = event->button.windowID;
215 break;
216 case SDL_EVENTCATEGORY_WHEEL:
217 windowID = event->wheel.windowID;
218 break;
219 case SDL_EVENTCATEGORY_TFINGER:
220 windowID = event->tfinger.windowID;
221 break;
222 case SDL_EVENTCATEGORY_PPROXIMITY:
223 windowID = event->pproximity.windowID;
224 break;
225 case SDL_EVENTCATEGORY_PTOUCH:
226 windowID = event->ptouch.windowID;
227 break;
228 case SDL_EVENTCATEGORY_PBUTTON:
229 windowID = event->pbutton.windowID;
230 break;
231 case SDL_EVENTCATEGORY_PMOTION:
232 windowID = event->pmotion.windowID;
233 break;
234 case SDL_EVENTCATEGORY_PAXIS:
235 windowID = event->paxis.windowID;
236 break;
237 case SDL_EVENTCATEGORY_DROP:
238 windowID = event->drop.windowID;
239 break;
240 case SDL_EVENTCATEGORY_RENDER:
241 windowID = event->render.windowID;
242 break;
243 default:
244 // < 0 -> invalid event type (error is set by SDL_GetEventCategory)
245 // else -> event has no associated window (not an error)
246 return NULL;
247 }
248 return SDL_GetWindowFromID(windowID);
249}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_categories_c.h b/contrib/SDL-3.2.8/src/events/SDL_categories_c.h
new file mode 100644
index 0000000..31d926a
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_categories_c.h
@@ -0,0 +1,70 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_categories_c_h_
24#define SDL_categories_c_h_
25
26typedef enum SDL_EventCategory
27{
28 SDL_EVENTCATEGORY_UNKNOWN,
29 SDL_EVENTCATEGORY_SYSTEM,
30 SDL_EVENTCATEGORY_DISPLAY,
31 SDL_EVENTCATEGORY_WINDOW,
32 SDL_EVENTCATEGORY_KDEVICE,
33 SDL_EVENTCATEGORY_KEY,
34 SDL_EVENTCATEGORY_EDIT,
35 SDL_EVENTCATEGORY_EDIT_CANDIDATES,
36 SDL_EVENTCATEGORY_TEXT,
37 SDL_EVENTCATEGORY_MDEVICE,
38 SDL_EVENTCATEGORY_MOTION,
39 SDL_EVENTCATEGORY_BUTTON,
40 SDL_EVENTCATEGORY_WHEEL,
41 SDL_EVENTCATEGORY_JDEVICE,
42 SDL_EVENTCATEGORY_JAXIS,
43 SDL_EVENTCATEGORY_JBALL,
44 SDL_EVENTCATEGORY_JHAT,
45 SDL_EVENTCATEGORY_JBUTTON,
46 SDL_EVENTCATEGORY_JBATTERY,
47 SDL_EVENTCATEGORY_GDEVICE,
48 SDL_EVENTCATEGORY_GAXIS,
49 SDL_EVENTCATEGORY_GBUTTON,
50 SDL_EVENTCATEGORY_GTOUCHPAD,
51 SDL_EVENTCATEGORY_GSENSOR,
52 SDL_EVENTCATEGORY_ADEVICE,
53 SDL_EVENTCATEGORY_CDEVICE,
54 SDL_EVENTCATEGORY_SENSOR,
55 SDL_EVENTCATEGORY_QUIT,
56 SDL_EVENTCATEGORY_USER,
57 SDL_EVENTCATEGORY_TFINGER,
58 SDL_EVENTCATEGORY_PPROXIMITY,
59 SDL_EVENTCATEGORY_PTOUCH,
60 SDL_EVENTCATEGORY_PMOTION,
61 SDL_EVENTCATEGORY_PBUTTON,
62 SDL_EVENTCATEGORY_PAXIS,
63 SDL_EVENTCATEGORY_DROP,
64 SDL_EVENTCATEGORY_CLIPBOARD,
65 SDL_EVENTCATEGORY_RENDER,
66} SDL_EventCategory;
67
68extern SDL_EventCategory SDL_GetEventCategory(Uint32 type);
69
70#endif // SDL_categories_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_clipboardevents.c b/contrib/SDL-3.2.8/src/events/SDL_clipboardevents.c
new file mode 100644
index 0000000..d5cf8ad
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_clipboardevents.c
@@ -0,0 +1,57 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// Clipboard event handling code for SDL
24
25#include "SDL_events_c.h"
26#include "SDL_clipboardevents_c.h"
27#include "../video/SDL_clipboard_c.h"
28
29void SDL_SendClipboardUpdate(bool owner, char **mime_types, size_t num_mime_types)
30{
31 if (!owner) {
32 /* Clear our internal clipboard contents when external clipboard is set.
33 *
34 * Wayland recursively sends a data offer to the client from which the clipboard data originated,
35 * and as the client can't determine the origin of the offer, the clipboard must not be cleared,
36 * or the original data may be destroyed. Cleanup will be done in the backend when an offer
37 * cancellation event arrives.
38 */
39 if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") != 0) {
40 SDL_CancelClipboardData(0);
41 }
42
43 SDL_SaveClipboardMimeTypes((const char **)mime_types, num_mime_types);
44 }
45
46 if (SDL_EventEnabled(SDL_EVENT_CLIPBOARD_UPDATE)) {
47 SDL_Event event;
48 event.type = SDL_EVENT_CLIPBOARD_UPDATE;
49
50 SDL_ClipboardEvent *cevent = &event.clipboard;
51 cevent->timestamp = 0;
52 cevent->owner = owner;
53 cevent->mime_types = (const char **)mime_types;
54 cevent->num_mime_types = (Uint32)num_mime_types;
55 SDL_PushEvent(&event);
56 }
57}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_clipboardevents_c.h b/contrib/SDL-3.2.8/src/events/SDL_clipboardevents_c.h
new file mode 100644
index 0000000..0b0f628
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_clipboardevents_c.h
@@ -0,0 +1,28 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_clipboardevents_c_h_
24#define SDL_clipboardevents_c_h_
25
26extern void SDL_SendClipboardUpdate(bool owner, char **mime_types, size_t num_mime_types);
27
28#endif // SDL_clipboardevents_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_displayevents.c b/contrib/SDL-3.2.8/src/events/SDL_displayevents.c
new file mode 100644
index 0000000..e41f75c
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_displayevents.c
@@ -0,0 +1,64 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// Display event handling code for SDL
24
25#include "SDL_events_c.h"
26
27void SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1, int data2)
28{
29 if (!display || display->id == 0) {
30 return;
31 }
32 switch (displayevent) {
33 case SDL_EVENT_DISPLAY_ORIENTATION:
34 if (data1 == SDL_ORIENTATION_UNKNOWN || data1 == display->current_orientation) {
35 return;
36 }
37 display->current_orientation = (SDL_DisplayOrientation)data1;
38 break;
39 default:
40 break;
41 }
42
43 // Post the event, if desired
44 if (SDL_EventEnabled(displayevent)) {
45 SDL_Event event;
46 event.type = displayevent;
47 event.common.timestamp = 0;
48 event.display.displayID = display->id;
49 event.display.data1 = data1;
50 event.display.data2 = data2;
51 SDL_PushEvent(&event);
52 }
53
54 switch (displayevent) {
55 case SDL_EVENT_DISPLAY_ADDED:
56 SDL_OnDisplayAdded(display);
57 break;
58 case SDL_EVENT_DISPLAY_MOVED:
59 SDL_OnDisplayMoved(display);
60 break;
61 default:
62 break;
63 }
64}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_displayevents_c.h b/contrib/SDL-3.2.8/src/events/SDL_displayevents_c.h
new file mode 100644
index 0000000..ae0730c
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_displayevents_c.h
@@ -0,0 +1,28 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_displayevents_c_h_
24#define SDL_displayevents_c_h_
25
26extern void SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1, int data2);
27
28#endif // SDL_displayevents_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_dropevents.c b/contrib/SDL-3.2.8/src/events/SDL_dropevents.c
new file mode 100644
index 0000000..661f4f3
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_dropevents.c
@@ -0,0 +1,115 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// Drag and drop event handling code for SDL
24
25#include "SDL_events_c.h"
26#include "SDL_dropevents_c.h"
27
28#include "../video/SDL_sysvideo.h" // for SDL_Window internals.
29
30static bool SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *source, const char *data, float x, float y)
31{
32 static bool app_is_dropping = false;
33 static float last_drop_x = 0;
34 static float last_drop_y = 0;
35 bool posted = false;
36
37 // Post the event, if desired
38 if (SDL_EventEnabled(evtype)) {
39 const bool need_begin = window ? !window->is_dropping : !app_is_dropping;
40 SDL_Event event;
41
42 if (need_begin) {
43 SDL_zero(event);
44 event.type = SDL_EVENT_DROP_BEGIN;
45 event.common.timestamp = 0;
46 event.drop.windowID = window ? window->id : 0;
47 posted = SDL_PushEvent(&event);
48 if (!posted) {
49 return false;
50 }
51 if (window) {
52 window->is_dropping = true;
53 } else {
54 app_is_dropping = true;
55 }
56 }
57
58 SDL_zero(event);
59 event.type = evtype;
60 event.common.timestamp = 0;
61 if (source) {
62 event.drop.source = SDL_CreateTemporaryString(source);
63 if (!event.drop.source) {
64 return false;
65 }
66 }
67 if (data) {
68 event.drop.data = SDL_CreateTemporaryString(data);
69 if (!event.drop.data) {
70 return false;
71 }
72 }
73 event.drop.windowID = window ? window->id : 0;
74
75 if (evtype == SDL_EVENT_DROP_POSITION) {
76 last_drop_x = x;
77 last_drop_y = y;
78 }
79 event.drop.x = last_drop_x;
80 event.drop.y = last_drop_y;
81 posted = SDL_PushEvent(&event);
82
83 if (posted && (evtype == SDL_EVENT_DROP_COMPLETE)) {
84 if (window) {
85 window->is_dropping = false;
86 } else {
87 app_is_dropping = false;
88 }
89
90 last_drop_x = 0;
91 last_drop_y = 0;
92 }
93 }
94 return posted;
95}
96
97bool SDL_SendDropFile(SDL_Window *window, const char *source, const char *file)
98{
99 return SDL_SendDrop(window, SDL_EVENT_DROP_FILE, source, file, 0, 0);
100}
101
102bool SDL_SendDropPosition(SDL_Window *window, float x, float y)
103{
104 return SDL_SendDrop(window, SDL_EVENT_DROP_POSITION, NULL, NULL, x, y);
105}
106
107bool SDL_SendDropText(SDL_Window *window, const char *text)
108{
109 return SDL_SendDrop(window, SDL_EVENT_DROP_TEXT, NULL, text, 0, 0);
110}
111
112bool SDL_SendDropComplete(SDL_Window *window)
113{
114 return SDL_SendDrop(window, SDL_EVENT_DROP_COMPLETE, NULL, NULL, 0, 0);
115}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_dropevents_c.h b/contrib/SDL-3.2.8/src/events/SDL_dropevents_c.h
new file mode 100644
index 0000000..efce0ac
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_dropevents_c.h
@@ -0,0 +1,31 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_dropevents_c_h_
24#define SDL_dropevents_c_h_
25
26extern bool SDL_SendDropFile(SDL_Window *window, const char *source, const char *file);
27extern bool SDL_SendDropPosition(SDL_Window *window, float x, float y);
28extern bool SDL_SendDropText(SDL_Window *window, const char *text);
29extern bool SDL_SendDropComplete(SDL_Window *window);
30
31#endif // SDL_dropevents_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_events.c b/contrib/SDL-3.2.8/src/events/SDL_events.c
new file mode 100644
index 0000000..349d575
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_events.c
@@ -0,0 +1,1987 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// General event handling code for SDL
24
25#include "SDL_events_c.h"
26#include "SDL_eventwatch_c.h"
27#include "SDL_windowevents_c.h"
28#include "../SDL_hints_c.h"
29#include "../audio/SDL_audio_c.h"
30#include "../camera/SDL_camera_c.h"
31#include "../timer/SDL_timer_c.h"
32#ifndef SDL_JOYSTICK_DISABLED
33#include "../joystick/SDL_joystick_c.h"
34#endif
35#ifndef SDL_SENSOR_DISABLED
36#include "../sensor/SDL_sensor_c.h"
37#endif
38#include "../video/SDL_sysvideo.h"
39
40#ifdef SDL_PLATFORM_ANDROID
41#include "../core/android/SDL_android.h"
42#include "../video/android/SDL_androidevents.h"
43#endif
44
45// An arbitrary limit so we don't have unbounded growth
46#define SDL_MAX_QUEUED_EVENTS 65535
47
48// Determines how often we pump events if joystick or sensor subsystems are active
49#define ENUMERATION_POLL_INTERVAL_NS (3 * SDL_NS_PER_SECOND)
50
51// Determines how often to pump events if joysticks or sensors are actively being read
52#define EVENT_POLL_INTERVAL_NS SDL_MS_TO_NS(1)
53
54// Make sure the type in the SDL_Event aligns properly across the union
55SDL_COMPILE_TIME_ASSERT(SDL_Event_type, sizeof(Uint32) == sizeof(SDL_EventType));
56
57#define SDL2_SYSWMEVENT 0x201
58
59#ifdef SDL_VIDEO_DRIVER_WINDOWS
60#include "../core/windows/SDL_windows.h"
61#endif
62
63#ifdef SDL_VIDEO_DRIVER_X11
64#include <X11/Xlib.h>
65#endif
66
67typedef struct SDL2_version
68{
69 Uint8 major;
70 Uint8 minor;
71 Uint8 patch;
72} SDL2_version;
73
74typedef enum
75{
76 SDL2_SYSWM_UNKNOWN
77} SDL2_SYSWM_TYPE;
78
79typedef struct SDL2_SysWMmsg
80{
81 SDL2_version version;
82 SDL2_SYSWM_TYPE subsystem;
83 union
84 {
85#ifdef SDL_VIDEO_DRIVER_WINDOWS
86 struct {
87 HWND hwnd; /**< The window for the message */
88 UINT msg; /**< The type of message */
89 WPARAM wParam; /**< WORD message parameter */
90 LPARAM lParam; /**< LONG message parameter */
91 } win;
92#endif
93#ifdef SDL_VIDEO_DRIVER_X11
94 struct {
95 XEvent event;
96 } x11;
97#endif
98 /* Can't have an empty union */
99 int dummy;
100 } msg;
101} SDL2_SysWMmsg;
102
103static SDL_EventWatchList SDL_event_watchers;
104static SDL_AtomicInt SDL_sentinel_pending;
105static Uint32 SDL_last_event_id = 0;
106
107typedef struct
108{
109 Uint32 bits[8];
110} SDL_DisabledEventBlock;
111
112static SDL_DisabledEventBlock *SDL_disabled_events[256];
113static SDL_AtomicInt SDL_userevents;
114
115typedef struct SDL_TemporaryMemory
116{
117 void *memory;
118 struct SDL_TemporaryMemory *prev;
119 struct SDL_TemporaryMemory *next;
120} SDL_TemporaryMemory;
121
122typedef struct SDL_TemporaryMemoryState
123{
124 SDL_TemporaryMemory *head;
125 SDL_TemporaryMemory *tail;
126} SDL_TemporaryMemoryState;
127
128static SDL_TLSID SDL_temporary_memory;
129
130typedef struct SDL_EventEntry
131{
132 SDL_Event event;
133 SDL_TemporaryMemory *memory;
134 struct SDL_EventEntry *prev;
135 struct SDL_EventEntry *next;
136} SDL_EventEntry;
137
138static struct
139{
140 SDL_Mutex *lock;
141 bool active;
142 SDL_AtomicInt count;
143 int max_events_seen;
144 SDL_EventEntry *head;
145 SDL_EventEntry *tail;
146 SDL_EventEntry *free;
147} SDL_EventQ = { NULL, false, { 0 }, 0, NULL, NULL, NULL };
148
149
150static void SDL_CleanupTemporaryMemory(void *data)
151{
152 SDL_TemporaryMemoryState *state = (SDL_TemporaryMemoryState *)data;
153
154 SDL_FreeTemporaryMemory();
155 SDL_free(state);
156}
157
158static SDL_TemporaryMemoryState *SDL_GetTemporaryMemoryState(bool create)
159{
160 SDL_TemporaryMemoryState *state;
161
162 state = (SDL_TemporaryMemoryState *)SDL_GetTLS(&SDL_temporary_memory);
163 if (!state) {
164 if (!create) {
165 return NULL;
166 }
167
168 state = (SDL_TemporaryMemoryState *)SDL_calloc(1, sizeof(*state));
169 if (!state) {
170 return NULL;
171 }
172
173 if (!SDL_SetTLS(&SDL_temporary_memory, state, SDL_CleanupTemporaryMemory)) {
174 SDL_free(state);
175 return NULL;
176 }
177 }
178 return state;
179}
180
181static SDL_TemporaryMemory *SDL_GetTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, const void *mem)
182{
183 SDL_TemporaryMemory *entry;
184
185 // Start from the end, it's likely to have been recently allocated
186 for (entry = state->tail; entry; entry = entry->prev) {
187 if (mem == entry->memory) {
188 return entry;
189 }
190 }
191 return NULL;
192}
193
194static void SDL_LinkTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, SDL_TemporaryMemory *entry)
195{
196 entry->prev = state->tail;
197 entry->next = NULL;
198
199 if (state->tail) {
200 state->tail->next = entry;
201 } else {
202 state->head = entry;
203 }
204 state->tail = entry;
205}
206
207static void SDL_UnlinkTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, SDL_TemporaryMemory *entry)
208{
209 if (state->head == entry) {
210 state->head = entry->next;
211 }
212 if (state->tail == entry) {
213 state->tail = entry->prev;
214 }
215
216 if (entry->prev) {
217 entry->prev->next = entry->next;
218 }
219 if (entry->next) {
220 entry->next->prev = entry->prev;
221 }
222
223 entry->prev = NULL;
224 entry->next = NULL;
225}
226
227static void SDL_FreeTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, SDL_TemporaryMemory *entry, bool free_data)
228{
229 if (free_data) {
230 SDL_free(entry->memory);
231 }
232 SDL_free(entry);
233}
234
235static void SDL_LinkTemporaryMemoryToEvent(SDL_EventEntry *event, const void *mem)
236{
237 SDL_TemporaryMemoryState *state;
238 SDL_TemporaryMemory *entry;
239
240 state = SDL_GetTemporaryMemoryState(false);
241 if (!state) {
242 return;
243 }
244
245 entry = SDL_GetTemporaryMemoryEntry(state, mem);
246 if (entry) {
247 SDL_UnlinkTemporaryMemoryEntry(state, entry);
248 entry->next = event->memory;
249 event->memory = entry;
250 }
251}
252
253static void SDL_TransferSysWMMemoryToEvent(SDL_EventEntry *event)
254{
255 SDL2_SysWMmsg **wmmsg = (SDL2_SysWMmsg **)((&event->event.common)+1);
256 SDL2_SysWMmsg *mem = SDL_AllocateTemporaryMemory(sizeof(*mem));
257 if (mem) {
258 SDL_copyp(mem, *wmmsg);
259 *wmmsg = mem;
260 SDL_LinkTemporaryMemoryToEvent(event, mem);
261 }
262}
263
264// Transfer the event memory from the thread-local event memory list to the event
265static void SDL_TransferTemporaryMemoryToEvent(SDL_EventEntry *event)
266{
267 switch (event->event.type) {
268 case SDL_EVENT_TEXT_EDITING:
269 SDL_LinkTemporaryMemoryToEvent(event, event->event.edit.text);
270 break;
271 case SDL_EVENT_TEXT_EDITING_CANDIDATES:
272 SDL_LinkTemporaryMemoryToEvent(event, event->event.edit_candidates.candidates);
273 break;
274 case SDL_EVENT_TEXT_INPUT:
275 SDL_LinkTemporaryMemoryToEvent(event, event->event.text.text);
276 break;
277 case SDL_EVENT_DROP_BEGIN:
278 case SDL_EVENT_DROP_FILE:
279 case SDL_EVENT_DROP_TEXT:
280 case SDL_EVENT_DROP_COMPLETE:
281 case SDL_EVENT_DROP_POSITION:
282 SDL_LinkTemporaryMemoryToEvent(event, event->event.drop.source);
283 SDL_LinkTemporaryMemoryToEvent(event, event->event.drop.data);
284 break;
285 case SDL_EVENT_CLIPBOARD_UPDATE:
286 SDL_LinkTemporaryMemoryToEvent(event, event->event.clipboard.mime_types);
287 break;
288 case SDL2_SYSWMEVENT:
289 // We need to copy the stack pointer into temporary memory
290 SDL_TransferSysWMMemoryToEvent(event);
291 break;
292 default:
293 break;
294 }
295}
296
297// Transfer the event memory from the event to the thread-local event memory list
298static void SDL_TransferTemporaryMemoryFromEvent(SDL_EventEntry *event)
299{
300 SDL_TemporaryMemoryState *state;
301 SDL_TemporaryMemory *entry, *next;
302
303 if (!event->memory) {
304 return;
305 }
306
307 state = SDL_GetTemporaryMemoryState(true);
308 if (!state) {
309 return; // this is now a leak, but you probably have bigger problems if malloc failed.
310 }
311
312 for (entry = event->memory; entry; entry = next) {
313 next = entry->next;
314 SDL_LinkTemporaryMemoryEntry(state, entry);
315 }
316 event->memory = NULL;
317}
318
319static void *SDL_FreeLater(void *memory)
320{
321 SDL_TemporaryMemoryState *state;
322
323 if (memory == NULL) {
324 return NULL;
325 }
326
327 // Make sure we're not adding this to the list twice
328 //SDL_assert(!SDL_ClaimTemporaryMemory(memory));
329
330 state = SDL_GetTemporaryMemoryState(true);
331 if (!state) {
332 return memory; // this is now a leak, but you probably have bigger problems if malloc failed.
333 }
334
335 SDL_TemporaryMemory *entry = (SDL_TemporaryMemory *)SDL_malloc(sizeof(*entry));
336 if (!entry) {
337 return memory; // this is now a leak, but you probably have bigger problems if malloc failed. We could probably pool up and reuse entries, though.
338 }
339
340 entry->memory = memory;
341
342 SDL_LinkTemporaryMemoryEntry(state, entry);
343
344 return memory;
345}
346
347void *SDL_AllocateTemporaryMemory(size_t size)
348{
349 return SDL_FreeLater(SDL_malloc(size));
350}
351
352const char *SDL_CreateTemporaryString(const char *string)
353{
354 if (string) {
355 return (const char *)SDL_FreeLater(SDL_strdup(string));
356 }
357 return NULL;
358}
359
360void *SDL_ClaimTemporaryMemory(const void *mem)
361{
362 SDL_TemporaryMemoryState *state;
363
364 state = SDL_GetTemporaryMemoryState(false);
365 if (state && mem) {
366 SDL_TemporaryMemory *entry = SDL_GetTemporaryMemoryEntry(state, mem);
367 if (entry) {
368 SDL_UnlinkTemporaryMemoryEntry(state, entry);
369 SDL_FreeTemporaryMemoryEntry(state, entry, false);
370 return (void *)mem;
371 }
372 }
373 return NULL;
374}
375
376void SDL_FreeTemporaryMemory(void)
377{
378 SDL_TemporaryMemoryState *state;
379
380 state = SDL_GetTemporaryMemoryState(false);
381 if (!state) {
382 return;
383 }
384
385 while (state->head) {
386 SDL_TemporaryMemory *entry = state->head;
387
388 SDL_UnlinkTemporaryMemoryEntry(state, entry);
389 SDL_FreeTemporaryMemoryEntry(state, entry, true);
390 }
391}
392
393#ifndef SDL_JOYSTICK_DISABLED
394
395static bool SDL_update_joysticks = true;
396
397static void SDLCALL SDL_AutoUpdateJoysticksChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
398{
399 SDL_update_joysticks = SDL_GetStringBoolean(hint, true);
400}
401
402#endif // !SDL_JOYSTICK_DISABLED
403
404#ifndef SDL_SENSOR_DISABLED
405
406static bool SDL_update_sensors = true;
407
408static void SDLCALL SDL_AutoUpdateSensorsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
409{
410 SDL_update_sensors = SDL_GetStringBoolean(hint, true);
411}
412
413#endif // !SDL_SENSOR_DISABLED
414
415static void SDLCALL SDL_PollSentinelChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
416{
417 SDL_SetEventEnabled(SDL_EVENT_POLL_SENTINEL, SDL_GetStringBoolean(hint, true));
418}
419
420/**
421 * Verbosity of logged events as defined in SDL_HINT_EVENT_LOGGING:
422 * - 0: (default) no logging
423 * - 1: logging of most events
424 * - 2: as above, plus mouse, pen, and finger motion
425 */
426static int SDL_EventLoggingVerbosity = 0;
427
428static void SDLCALL SDL_EventLoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
429{
430 SDL_EventLoggingVerbosity = (hint && *hint) ? SDL_clamp(SDL_atoi(hint), 0, 3) : 0;
431}
432
433static void SDL_LogEvent(const SDL_Event *event)
434{
435 static const char *pen_axisnames[] = { "PRESSURE", "XTILT", "YTILT", "DISTANCE", "ROTATION", "SLIDER", "TANGENTIAL_PRESSURE" };
436 SDL_COMPILE_TIME_ASSERT(pen_axisnames_array_matches, SDL_arraysize(pen_axisnames) == SDL_PEN_AXIS_COUNT);
437
438 char name[64];
439 char details[128];
440
441 // sensor/mouse/pen/finger motion are spammy, ignore these if they aren't demanded.
442 if ((SDL_EventLoggingVerbosity < 2) &&
443 ((event->type == SDL_EVENT_MOUSE_MOTION) ||
444 (event->type == SDL_EVENT_FINGER_MOTION) ||
445 (event->type == SDL_EVENT_PEN_AXIS) ||
446 (event->type == SDL_EVENT_PEN_MOTION) ||
447 (event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION) ||
448 (event->type == SDL_EVENT_GAMEPAD_SENSOR_UPDATE) ||
449 (event->type == SDL_EVENT_SENSOR_UPDATE))) {
450 return;
451 }
452
453// this is to make (void)SDL_snprintf() calls cleaner.
454#define uint unsigned int
455
456 name[0] = '\0';
457 details[0] = '\0';
458
459 // !!! FIXME: This code is kinda ugly, sorry.
460
461 if ((event->type >= SDL_EVENT_USER) && (event->type <= SDL_EVENT_LAST)) {
462 char plusstr[16];
463 SDL_strlcpy(name, "SDL_EVENT_USER", sizeof(name));
464 if (event->type > SDL_EVENT_USER) {
465 (void)SDL_snprintf(plusstr, sizeof(plusstr), "+%u", ((uint)event->type) - SDL_EVENT_USER);
466 } else {
467 plusstr[0] = '\0';
468 }
469 (void)SDL_snprintf(details, sizeof(details), "%s (timestamp=%u windowid=%u code=%d data1=%p data2=%p)",
470 plusstr, (uint)event->user.timestamp, (uint)event->user.windowID,
471 (int)event->user.code, event->user.data1, event->user.data2);
472 }
473
474 switch (event->type) {
475#define SDL_EVENT_CASE(x) \
476 case x: \
477 SDL_strlcpy(name, #x, sizeof(name));
478 SDL_EVENT_CASE(SDL_EVENT_FIRST)
479 SDL_strlcpy(details, " (THIS IS PROBABLY A BUG!)", sizeof(details));
480 break;
481 SDL_EVENT_CASE(SDL_EVENT_QUIT)
482 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u)", (uint)event->quit.timestamp);
483 break;
484 SDL_EVENT_CASE(SDL_EVENT_TERMINATING)
485 break;
486 SDL_EVENT_CASE(SDL_EVENT_LOW_MEMORY)
487 break;
488 SDL_EVENT_CASE(SDL_EVENT_WILL_ENTER_BACKGROUND)
489 break;
490 SDL_EVENT_CASE(SDL_EVENT_DID_ENTER_BACKGROUND)
491 break;
492 SDL_EVENT_CASE(SDL_EVENT_WILL_ENTER_FOREGROUND)
493 break;
494 SDL_EVENT_CASE(SDL_EVENT_DID_ENTER_FOREGROUND)
495 break;
496 SDL_EVENT_CASE(SDL_EVENT_LOCALE_CHANGED)
497 break;
498 SDL_EVENT_CASE(SDL_EVENT_SYSTEM_THEME_CHANGED)
499 break;
500 SDL_EVENT_CASE(SDL_EVENT_KEYMAP_CHANGED)
501 break;
502 SDL_EVENT_CASE(SDL_EVENT_CLIPBOARD_UPDATE)
503 break;
504
505#define SDL_RENDEREVENT_CASE(x) \
506 case x: \
507 SDL_strlcpy(name, #x, sizeof(name)); \
508 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u event=%s windowid=%u)", \
509 (uint)event->display.timestamp, name, (uint)event->render.windowID); \
510 break
511 SDL_RENDEREVENT_CASE(SDL_EVENT_RENDER_TARGETS_RESET);
512 SDL_RENDEREVENT_CASE(SDL_EVENT_RENDER_DEVICE_RESET);
513 SDL_RENDEREVENT_CASE(SDL_EVENT_RENDER_DEVICE_LOST);
514
515#define SDL_DISPLAYEVENT_CASE(x) \
516 case x: \
517 SDL_strlcpy(name, #x, sizeof(name)); \
518 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u display=%u event=%s data1=%d, data2=%d)", \
519 (uint)event->display.timestamp, (uint)event->display.displayID, name, (int)event->display.data1, (int)event->display.data2); \
520 break
521 SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ORIENTATION);
522 SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ADDED);
523 SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_REMOVED);
524 SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_MOVED);
525 SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED);
526 SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED);
527 SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED);
528#undef SDL_DISPLAYEVENT_CASE
529
530#define SDL_WINDOWEVENT_CASE(x) \
531 case x: \
532 SDL_strlcpy(name, #x, sizeof(name)); \
533 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u event=%s data1=%d data2=%d)", \
534 (uint)event->window.timestamp, (uint)event->window.windowID, name, (int)event->window.data1, (int)event->window.data2); \
535 break
536 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_SHOWN);
537 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_HIDDEN);
538 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_EXPOSED);
539 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOVED);
540 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESIZED);
541 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED);
542 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_METAL_VIEW_RESIZED);
543 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_SAFE_AREA_CHANGED);
544 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MINIMIZED);
545 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MAXIMIZED);
546 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESTORED);
547 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_ENTER);
548 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_LEAVE);
549 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_GAINED);
550 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_LOST);
551 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_CLOSE_REQUESTED);
552 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_HIT_TEST);
553 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_ICCPROF_CHANGED);
554 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DISPLAY_CHANGED);
555 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED);
556 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_OCCLUDED);
557 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_ENTER_FULLSCREEN);
558 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_LEAVE_FULLSCREEN);
559 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DESTROYED);
560 SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_HDR_STATE_CHANGED);
561#undef SDL_WINDOWEVENT_CASE
562
563#define PRINT_KEYDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->kdevice.timestamp, (uint)event->kdevice.which)
564 SDL_EVENT_CASE(SDL_EVENT_KEYBOARD_ADDED)
565 PRINT_KEYDEV_EVENT(event);
566 break;
567 SDL_EVENT_CASE(SDL_EVENT_KEYBOARD_REMOVED)
568 PRINT_KEYDEV_EVENT(event);
569 break;
570#undef PRINT_KEYDEV_EVENT
571
572#define PRINT_KEY_EVENT(event) \
573 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%s repeat=%s scancode=%u keycode=%u mod=0x%x)", \
574 (uint)event->key.timestamp, (uint)event->key.windowID, (uint)event->key.which, \
575 event->key.down ? "pressed" : "released", \
576 event->key.repeat ? "true" : "false", \
577 (uint)event->key.scancode, \
578 (uint)event->key.key, \
579 (uint)event->key.mod)
580 SDL_EVENT_CASE(SDL_EVENT_KEY_DOWN)
581 PRINT_KEY_EVENT(event);
582 break;
583 SDL_EVENT_CASE(SDL_EVENT_KEY_UP)
584 PRINT_KEY_EVENT(event);
585 break;
586#undef PRINT_KEY_EVENT
587
588 SDL_EVENT_CASE(SDL_EVENT_TEXT_EDITING)
589 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u text='%s' start=%d length=%d)",
590 (uint)event->edit.timestamp, (uint)event->edit.windowID,
591 event->edit.text, (int)event->edit.start, (int)event->edit.length);
592 break;
593
594 SDL_EVENT_CASE(SDL_EVENT_TEXT_EDITING_CANDIDATES)
595 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u num_candidates=%d selected_candidate=%d)",
596 (uint)event->edit_candidates.timestamp, (uint)event->edit_candidates.windowID,
597 (int)event->edit_candidates.num_candidates, (int)event->edit_candidates.selected_candidate);
598 break;
599
600 SDL_EVENT_CASE(SDL_EVENT_TEXT_INPUT)
601 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u text='%s')", (uint)event->text.timestamp, (uint)event->text.windowID, event->text.text);
602 break;
603
604#define PRINT_MOUSEDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->mdevice.timestamp, (uint)event->mdevice.which)
605 SDL_EVENT_CASE(SDL_EVENT_MOUSE_ADDED)
606 PRINT_MOUSEDEV_EVENT(event);
607 break;
608 SDL_EVENT_CASE(SDL_EVENT_MOUSE_REMOVED)
609 PRINT_MOUSEDEV_EVENT(event);
610 break;
611#undef PRINT_MOUSEDEV_EVENT
612
613 SDL_EVENT_CASE(SDL_EVENT_MOUSE_MOTION)
614 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%u x=%g y=%g xrel=%g yrel=%g)",
615 (uint)event->motion.timestamp, (uint)event->motion.windowID,
616 (uint)event->motion.which, (uint)event->motion.state,
617 event->motion.x, event->motion.y,
618 event->motion.xrel, event->motion.yrel);
619 break;
620
621#define PRINT_MBUTTON_EVENT(event) \
622 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u button=%u state=%s clicks=%u x=%g y=%g)", \
623 (uint)event->button.timestamp, (uint)event->button.windowID, \
624 (uint)event->button.which, (uint)event->button.button, \
625 event->button.down ? "pressed" : "released", \
626 (uint)event->button.clicks, event->button.x, event->button.y)
627 SDL_EVENT_CASE(SDL_EVENT_MOUSE_BUTTON_DOWN)
628 PRINT_MBUTTON_EVENT(event);
629 break;
630 SDL_EVENT_CASE(SDL_EVENT_MOUSE_BUTTON_UP)
631 PRINT_MBUTTON_EVENT(event);
632 break;
633#undef PRINT_MBUTTON_EVENT
634
635 SDL_EVENT_CASE(SDL_EVENT_MOUSE_WHEEL)
636 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u x=%g y=%g direction=%s)",
637 (uint)event->wheel.timestamp, (uint)event->wheel.windowID,
638 (uint)event->wheel.which, event->wheel.x, event->wheel.y,
639 event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped");
640 break;
641
642 SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_AXIS_MOTION)
643 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d axis=%u value=%d)",
644 (uint)event->jaxis.timestamp, (int)event->jaxis.which,
645 (uint)event->jaxis.axis, (int)event->jaxis.value);
646 break;
647
648 SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BALL_MOTION)
649 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d ball=%u xrel=%d yrel=%d)",
650 (uint)event->jball.timestamp, (int)event->jball.which,
651 (uint)event->jball.ball, (int)event->jball.xrel, (int)event->jball.yrel);
652 break;
653
654 SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_HAT_MOTION)
655 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d hat=%u value=%u)",
656 (uint)event->jhat.timestamp, (int)event->jhat.which,
657 (uint)event->jhat.hat, (uint)event->jhat.value);
658 break;
659
660#define PRINT_JBUTTON_EVENT(event) \
661 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d button=%u state=%s)", \
662 (uint)event->jbutton.timestamp, (int)event->jbutton.which, \
663 (uint)event->jbutton.button, event->jbutton.down ? "pressed" : "released")
664 SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BUTTON_DOWN)
665 PRINT_JBUTTON_EVENT(event);
666 break;
667 SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BUTTON_UP)
668 PRINT_JBUTTON_EVENT(event);
669 break;
670#undef PRINT_JBUTTON_EVENT
671
672 SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BATTERY_UPDATED)
673 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d state=%u percent=%d)",
674 (uint)event->jbattery.timestamp, (int)event->jbattery.which,
675 event->jbattery.state, event->jbattery.percent);
676 break;
677
678#define PRINT_JOYDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d)", (uint)event->jdevice.timestamp, (int)event->jdevice.which)
679 SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_ADDED)
680 PRINT_JOYDEV_EVENT(event);
681 break;
682 SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_REMOVED)
683 PRINT_JOYDEV_EVENT(event);
684 break;
685 SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE)
686 PRINT_JOYDEV_EVENT(event);
687 break;
688#undef PRINT_JOYDEV_EVENT
689
690 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_AXIS_MOTION)
691 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d axis=%u value=%d)",
692 (uint)event->gaxis.timestamp, (int)event->gaxis.which,
693 (uint)event->gaxis.axis, (int)event->gaxis.value);
694 break;
695
696#define PRINT_CBUTTON_EVENT(event) \
697 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d button=%u state=%s)", \
698 (uint)event->gbutton.timestamp, (int)event->gbutton.which, \
699 (uint)event->gbutton.button, event->gbutton.down ? "pressed" : "released")
700 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_BUTTON_DOWN)
701 PRINT_CBUTTON_EVENT(event);
702 break;
703 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_BUTTON_UP)
704 PRINT_CBUTTON_EVENT(event);
705 break;
706#undef PRINT_CBUTTON_EVENT
707
708#define PRINT_GAMEPADDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d)", (uint)event->gdevice.timestamp, (int)event->gdevice.which)
709 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_ADDED)
710 PRINT_GAMEPADDEV_EVENT(event);
711 break;
712 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_REMOVED)
713 PRINT_GAMEPADDEV_EVENT(event);
714 break;
715 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_REMAPPED)
716 PRINT_GAMEPADDEV_EVENT(event);
717 break;
718 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_UPDATE_COMPLETE)
719 PRINT_GAMEPADDEV_EVENT(event);
720 break;
721 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED)
722 PRINT_GAMEPADDEV_EVENT(event);
723 break;
724#undef PRINT_GAMEPADDEV_EVENT
725
726#define PRINT_CTOUCHPAD_EVENT(event) \
727 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d touchpad=%d finger=%d x=%f y=%f pressure=%f)", \
728 (uint)event->gtouchpad.timestamp, (int)event->gtouchpad.which, \
729 (int)event->gtouchpad.touchpad, (int)event->gtouchpad.finger, \
730 event->gtouchpad.x, event->gtouchpad.y, event->gtouchpad.pressure)
731 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN)
732 PRINT_CTOUCHPAD_EVENT(event);
733 break;
734 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_TOUCHPAD_UP)
735 PRINT_CTOUCHPAD_EVENT(event);
736 break;
737 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION)
738 PRINT_CTOUCHPAD_EVENT(event);
739 break;
740#undef PRINT_CTOUCHPAD_EVENT
741
742 SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_SENSOR_UPDATE)
743 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d sensor=%d data[0]=%f data[1]=%f data[2]=%f)",
744 (uint)event->gsensor.timestamp, (int)event->gsensor.which, (int)event->gsensor.sensor,
745 event->gsensor.data[0], event->gsensor.data[1], event->gsensor.data[2]);
746 break;
747
748#define PRINT_FINGER_EVENT(event) \
749 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u touchid=%" SDL_PRIu64 " fingerid=%" SDL_PRIu64 " x=%f y=%f dx=%f dy=%f pressure=%f)", \
750 (uint)event->tfinger.timestamp, event->tfinger.touchID, \
751 event->tfinger.fingerID, event->tfinger.x, event->tfinger.y, \
752 event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure)
753 SDL_EVENT_CASE(SDL_EVENT_FINGER_DOWN)
754 PRINT_FINGER_EVENT(event);
755 break;
756 SDL_EVENT_CASE(SDL_EVENT_FINGER_UP)
757 PRINT_FINGER_EVENT(event);
758 break;
759 SDL_EVENT_CASE(SDL_EVENT_FINGER_CANCELED)
760 PRINT_FINGER_EVENT(event);
761 break;
762 SDL_EVENT_CASE(SDL_EVENT_FINGER_MOTION)
763 PRINT_FINGER_EVENT(event);
764 break;
765#undef PRINT_FINGER_EVENT
766
767#define PRINT_PTOUCH_EVENT(event) \
768 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g eraser=%s state=%s)", \
769 (uint)event->ptouch.timestamp, (uint)event->ptouch.windowID, (uint)event->ptouch.which, (uint)event->ptouch.pen_state, event->ptouch.x, event->ptouch.y, \
770 event->ptouch.eraser ? "yes" : "no", event->ptouch.down ? "down" : "up");
771 SDL_EVENT_CASE(SDL_EVENT_PEN_DOWN)
772 PRINT_PTOUCH_EVENT(event);
773 break;
774 SDL_EVENT_CASE(SDL_EVENT_PEN_UP)
775 PRINT_PTOUCH_EVENT(event);
776 break;
777#undef PRINT_PTOUCH_EVENT
778
779#define PRINT_PPROXIMITY_EVENT(event) \
780 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u)", \
781 (uint)event->pproximity.timestamp, (uint)event->pproximity.windowID, (uint)event->pproximity.which);
782 SDL_EVENT_CASE(SDL_EVENT_PEN_PROXIMITY_IN)
783 PRINT_PPROXIMITY_EVENT(event);
784 break;
785 SDL_EVENT_CASE(SDL_EVENT_PEN_PROXIMITY_OUT)
786 PRINT_PPROXIMITY_EVENT(event);
787 break;
788#undef PRINT_PPROXIMITY_EVENT
789
790 SDL_EVENT_CASE(SDL_EVENT_PEN_AXIS)
791 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g axis=%s value=%g)",
792 (uint)event->paxis.timestamp, (uint)event->paxis.windowID, (uint)event->paxis.which, (uint)event->paxis.pen_state, event->paxis.x, event->paxis.y,
793 ((((int) event->paxis.axis) >= 0) && (event->paxis.axis < SDL_arraysize(pen_axisnames))) ? pen_axisnames[event->paxis.axis] : "[UNKNOWN]", event->paxis.value);
794 break;
795
796 SDL_EVENT_CASE(SDL_EVENT_PEN_MOTION)
797 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g)",
798 (uint)event->pmotion.timestamp, (uint)event->pmotion.windowID, (uint)event->pmotion.which, (uint)event->pmotion.pen_state, event->pmotion.x, event->pmotion.y);
799 break;
800
801#define PRINT_PBUTTON_EVENT(event) \
802 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g button=%u state=%s)", \
803 (uint)event->pbutton.timestamp, (uint)event->pbutton.windowID, (uint)event->pbutton.which, (uint)event->pbutton.pen_state, event->pbutton.x, event->pbutton.y, \
804 (uint)event->pbutton.button, event->pbutton.down ? "down" : "up");
805 SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_DOWN)
806 PRINT_PBUTTON_EVENT(event);
807 break;
808 SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_UP)
809 PRINT_PBUTTON_EVENT(event);
810 break;
811#undef PRINT_PBUTTON_EVENT
812
813#define PRINT_DROP_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (data='%s' timestamp=%u windowid=%u x=%f y=%f)", event->drop.data, (uint)event->drop.timestamp, (uint)event->drop.windowID, event->drop.x, event->drop.y)
814 SDL_EVENT_CASE(SDL_EVENT_DROP_FILE)
815 PRINT_DROP_EVENT(event);
816 break;
817 SDL_EVENT_CASE(SDL_EVENT_DROP_TEXT)
818 PRINT_DROP_EVENT(event);
819 break;
820 SDL_EVENT_CASE(SDL_EVENT_DROP_BEGIN)
821 PRINT_DROP_EVENT(event);
822 break;
823 SDL_EVENT_CASE(SDL_EVENT_DROP_COMPLETE)
824 PRINT_DROP_EVENT(event);
825 break;
826 SDL_EVENT_CASE(SDL_EVENT_DROP_POSITION)
827 PRINT_DROP_EVENT(event);
828 break;
829#undef PRINT_DROP_EVENT
830
831#define PRINT_AUDIODEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u recording=%s)", (uint)event->adevice.timestamp, (uint)event->adevice.which, event->adevice.recording ? "true" : "false")
832 SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_ADDED)
833 PRINT_AUDIODEV_EVENT(event);
834 break;
835 SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_REMOVED)
836 PRINT_AUDIODEV_EVENT(event);
837 break;
838 SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED)
839 PRINT_AUDIODEV_EVENT(event);
840 break;
841#undef PRINT_AUDIODEV_EVENT
842
843#define PRINT_CAMERADEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->cdevice.timestamp, (uint)event->cdevice.which)
844 SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_ADDED)
845 PRINT_CAMERADEV_EVENT(event);
846 break;
847 SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_REMOVED)
848 PRINT_CAMERADEV_EVENT(event);
849 break;
850 SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_APPROVED)
851 PRINT_CAMERADEV_EVENT(event);
852 break;
853 SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_DENIED)
854 PRINT_CAMERADEV_EVENT(event);
855 break;
856#undef PRINT_CAMERADEV_EVENT
857
858 SDL_EVENT_CASE(SDL_EVENT_SENSOR_UPDATE)
859 (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d data[0]=%f data[1]=%f data[2]=%f data[3]=%f data[4]=%f data[5]=%f)",
860 (uint)event->sensor.timestamp, (int)event->sensor.which,
861 event->sensor.data[0], event->sensor.data[1], event->sensor.data[2],
862 event->sensor.data[3], event->sensor.data[4], event->sensor.data[5]);
863 break;
864
865#undef SDL_EVENT_CASE
866
867 case SDL_EVENT_POLL_SENTINEL:
868 // No logging necessary for this one
869 break;
870
871 default:
872 if (!name[0]) {
873 if (event->type >= SDL_EVENT_USER) {
874 SDL_strlcpy(name, "USER", sizeof(name));
875 } else {
876 SDL_strlcpy(name, "UNKNOWN", sizeof(name));
877 }
878 (void)SDL_snprintf(details, sizeof(details), " 0x%x", (uint)event->type);
879 }
880 break;
881 }
882
883 if (name[0]) {
884 SDL_Log("SDL EVENT: %s%s", name, details);
885 }
886
887#undef uint
888}
889
890void SDL_StopEventLoop(void)
891{
892 const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS");
893 int i;
894 SDL_EventEntry *entry;
895
896 SDL_LockMutex(SDL_EventQ.lock);
897
898 SDL_EventQ.active = false;
899
900 if (report && SDL_atoi(report)) {
901 SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d",
902 SDL_EventQ.max_events_seen);
903 }
904
905 // Clean out EventQ
906 for (entry = SDL_EventQ.head; entry;) {
907 SDL_EventEntry *next = entry->next;
908 SDL_TransferTemporaryMemoryFromEvent(entry);
909 SDL_free(entry);
910 entry = next;
911 }
912 for (entry = SDL_EventQ.free; entry;) {
913 SDL_EventEntry *next = entry->next;
914 SDL_free(entry);
915 entry = next;
916 }
917
918 SDL_SetAtomicInt(&SDL_EventQ.count, 0);
919 SDL_EventQ.max_events_seen = 0;
920 SDL_EventQ.head = NULL;
921 SDL_EventQ.tail = NULL;
922 SDL_EventQ.free = NULL;
923 SDL_SetAtomicInt(&SDL_sentinel_pending, 0);
924
925 // Clear disabled event state
926 for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
927 SDL_free(SDL_disabled_events[i]);
928 SDL_disabled_events[i] = NULL;
929 }
930
931 SDL_QuitEventWatchList(&SDL_event_watchers);
932 SDL_QuitWindowEventWatch();
933
934 SDL_Mutex *lock = NULL;
935 if (SDL_EventQ.lock) {
936 lock = SDL_EventQ.lock;
937 SDL_EventQ.lock = NULL;
938 }
939
940 SDL_UnlockMutex(lock);
941
942 if (lock) {
943 SDL_DestroyMutex(lock);
944 }
945}
946
947// This function (and associated calls) may be called more than once
948bool SDL_StartEventLoop(void)
949{
950 /* We'll leave the event queue alone, since we might have gotten
951 some important events at launch (like SDL_EVENT_DROP_FILE)
952
953 FIXME: Does this introduce any other bugs with events at startup?
954 */
955
956 // Create the lock and set ourselves active
957#ifndef SDL_THREADS_DISABLED
958 if (!SDL_EventQ.lock) {
959 SDL_EventQ.lock = SDL_CreateMutex();
960 if (SDL_EventQ.lock == NULL) {
961 return false;
962 }
963 }
964 SDL_LockMutex(SDL_EventQ.lock);
965
966 if (!SDL_InitEventWatchList(&SDL_event_watchers)) {
967 SDL_UnlockMutex(SDL_EventQ.lock);
968 return false;
969 }
970#endif // !SDL_THREADS_DISABLED
971
972 SDL_InitWindowEventWatch();
973
974 SDL_EventQ.active = true;
975
976#ifndef SDL_THREADS_DISABLED
977 SDL_UnlockMutex(SDL_EventQ.lock);
978#endif
979 return true;
980}
981
982// Add an event to the event queue -- called with the queue locked
983static int SDL_AddEvent(SDL_Event *event)
984{
985 SDL_EventEntry *entry;
986 const int initial_count = SDL_GetAtomicInt(&SDL_EventQ.count);
987 int final_count;
988
989 if (initial_count >= SDL_MAX_QUEUED_EVENTS) {
990 SDL_SetError("Event queue is full (%d events)", initial_count);
991 return 0;
992 }
993
994 if (SDL_EventQ.free == NULL) {
995 entry = (SDL_EventEntry *)SDL_malloc(sizeof(*entry));
996 if (entry == NULL) {
997 return 0;
998 }
999 } else {
1000 entry = SDL_EventQ.free;
1001 SDL_EventQ.free = entry->next;
1002 }
1003
1004 if (SDL_EventLoggingVerbosity > 0) {
1005 SDL_LogEvent(event);
1006 }
1007
1008 SDL_copyp(&entry->event, event);
1009 if (event->type == SDL_EVENT_POLL_SENTINEL) {
1010 SDL_AddAtomicInt(&SDL_sentinel_pending, 1);
1011 }
1012 entry->memory = NULL;
1013 SDL_TransferTemporaryMemoryToEvent(entry);
1014
1015 if (SDL_EventQ.tail) {
1016 SDL_EventQ.tail->next = entry;
1017 entry->prev = SDL_EventQ.tail;
1018 SDL_EventQ.tail = entry;
1019 entry->next = NULL;
1020 } else {
1021 SDL_assert(!SDL_EventQ.head);
1022 SDL_EventQ.head = entry;
1023 SDL_EventQ.tail = entry;
1024 entry->prev = NULL;
1025 entry->next = NULL;
1026 }
1027
1028 final_count = SDL_AddAtomicInt(&SDL_EventQ.count, 1) + 1;
1029 if (final_count > SDL_EventQ.max_events_seen) {
1030 SDL_EventQ.max_events_seen = final_count;
1031 }
1032
1033 ++SDL_last_event_id;
1034
1035 return 1;
1036}
1037
1038// Remove an event from the queue -- called with the queue locked
1039static void SDL_CutEvent(SDL_EventEntry *entry)
1040{
1041 SDL_TransferTemporaryMemoryFromEvent(entry);
1042
1043 if (entry->prev) {
1044 entry->prev->next = entry->next;
1045 }
1046 if (entry->next) {
1047 entry->next->prev = entry->prev;
1048 }
1049
1050 if (entry == SDL_EventQ.head) {
1051 SDL_assert(entry->prev == NULL);
1052 SDL_EventQ.head = entry->next;
1053 }
1054 if (entry == SDL_EventQ.tail) {
1055 SDL_assert(entry->next == NULL);
1056 SDL_EventQ.tail = entry->prev;
1057 }
1058
1059 if (entry->event.type == SDL_EVENT_POLL_SENTINEL) {
1060 SDL_AddAtomicInt(&SDL_sentinel_pending, -1);
1061 }
1062
1063 entry->next = SDL_EventQ.free;
1064 SDL_EventQ.free = entry;
1065 SDL_assert(SDL_GetAtomicInt(&SDL_EventQ.count) > 0);
1066 SDL_AddAtomicInt(&SDL_EventQ.count, -1);
1067}
1068
1069static void SDL_SendWakeupEvent(void)
1070{
1071#ifdef SDL_PLATFORM_ANDROID
1072 Android_SendLifecycleEvent(SDL_ANDROID_LIFECYCLE_WAKE);
1073#else
1074 SDL_VideoDevice *_this = SDL_GetVideoDevice();
1075 if (_this == NULL || !_this->SendWakeupEvent) {
1076 return;
1077 }
1078
1079 SDL_LockMutex(_this->wakeup_lock);
1080 {
1081 if (_this->wakeup_window) {
1082 _this->SendWakeupEvent(_this, _this->wakeup_window);
1083
1084 // No more wakeup events needed until we enter a new wait
1085 _this->wakeup_window = NULL;
1086 }
1087 }
1088 SDL_UnlockMutex(_this->wakeup_lock);
1089#endif
1090}
1091
1092// Lock the event queue, take a peep at it, and unlock it
1093static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_EventAction action,
1094 Uint32 minType, Uint32 maxType, bool include_sentinel)
1095{
1096 int i, used, sentinels_expected = 0;
1097
1098 // Lock the event queue
1099 used = 0;
1100
1101 SDL_LockMutex(SDL_EventQ.lock);
1102 {
1103 // Don't look after we've quit
1104 if (!SDL_EventQ.active) {
1105 // We get a few spurious events at shutdown, so don't warn then
1106 if (action == SDL_GETEVENT) {
1107 SDL_SetError("The event system has been shut down");
1108 }
1109 SDL_UnlockMutex(SDL_EventQ.lock);
1110 return -1;
1111 }
1112 if (action == SDL_ADDEVENT) {
1113 if (!events) {
1114 SDL_UnlockMutex(SDL_EventQ.lock);
1115 return SDL_InvalidParamError("events");
1116 }
1117 for (i = 0; i < numevents; ++i) {
1118 used += SDL_AddEvent(&events[i]);
1119 }
1120 } else {
1121 SDL_EventEntry *entry, *next;
1122 Uint32 type;
1123
1124 for (entry = SDL_EventQ.head; entry && (events == NULL || used < numevents); entry = next) {
1125 next = entry->next;
1126 type = entry->event.type;
1127 if (minType <= type && type <= maxType) {
1128 if (events) {
1129 SDL_copyp(&events[used], &entry->event);
1130
1131 if (action == SDL_GETEVENT) {
1132 SDL_CutEvent(entry);
1133 }
1134 }
1135 if (type == SDL_EVENT_POLL_SENTINEL) {
1136 // Special handling for the sentinel event
1137 if (!include_sentinel) {
1138 // Skip it, we don't want to include it
1139 continue;
1140 }
1141 if (events == NULL || action != SDL_GETEVENT) {
1142 ++sentinels_expected;
1143 }
1144 if (SDL_GetAtomicInt(&SDL_sentinel_pending) > sentinels_expected) {
1145 // Skip it, there's another one pending
1146 continue;
1147 }
1148 }
1149 ++used;
1150 }
1151 }
1152 }
1153 }
1154 SDL_UnlockMutex(SDL_EventQ.lock);
1155
1156 if (used > 0 && action == SDL_ADDEVENT) {
1157 SDL_SendWakeupEvent();
1158 }
1159
1160 return used;
1161}
1162int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_EventAction action,
1163 Uint32 minType, Uint32 maxType)
1164{
1165 return SDL_PeepEventsInternal(events, numevents, action, minType, maxType, false);
1166}
1167
1168bool SDL_HasEvent(Uint32 type)
1169{
1170 return SDL_HasEvents(type, type);
1171}
1172
1173bool SDL_HasEvents(Uint32 minType, Uint32 maxType)
1174{
1175 bool found = false;
1176
1177 SDL_LockMutex(SDL_EventQ.lock);
1178 {
1179 if (SDL_EventQ.active) {
1180 for (SDL_EventEntry *entry = SDL_EventQ.head; entry; entry = entry->next) {
1181 const Uint32 type = entry->event.type;
1182 if (minType <= type && type <= maxType) {
1183 found = true;
1184 break;
1185 }
1186 }
1187 }
1188 }
1189 SDL_UnlockMutex(SDL_EventQ.lock);
1190
1191 return found;
1192}
1193
1194void SDL_FlushEvent(Uint32 type)
1195{
1196 SDL_FlushEvents(type, type);
1197}
1198
1199void SDL_FlushEvents(Uint32 minType, Uint32 maxType)
1200{
1201 SDL_EventEntry *entry, *next;
1202 Uint32 type;
1203
1204 // Make sure the events are current
1205#if 0
1206 /* Actually, we can't do this since we might be flushing while processing
1207 a resize event, and calling this might trigger further resize events.
1208 */
1209 SDL_PumpEvents();
1210#endif
1211
1212 // Lock the event queue
1213 SDL_LockMutex(SDL_EventQ.lock);
1214 {
1215 // Don't look after we've quit
1216 if (!SDL_EventQ.active) {
1217 SDL_UnlockMutex(SDL_EventQ.lock);
1218 return;
1219 }
1220 for (entry = SDL_EventQ.head; entry; entry = next) {
1221 next = entry->next;
1222 type = entry->event.type;
1223 if (minType <= type && type <= maxType) {
1224 SDL_CutEvent(entry);
1225 }
1226 }
1227 }
1228 SDL_UnlockMutex(SDL_EventQ.lock);
1229}
1230
1231typedef enum
1232{
1233 SDL_MAIN_CALLBACK_WAITING,
1234 SDL_MAIN_CALLBACK_COMPLETE,
1235 SDL_MAIN_CALLBACK_CANCELED,
1236} SDL_MainThreadCallbackState;
1237
1238typedef struct SDL_MainThreadCallbackEntry
1239{
1240 SDL_MainThreadCallback callback;
1241 void *userdata;
1242 SDL_AtomicInt state;
1243 SDL_Semaphore *semaphore;
1244 struct SDL_MainThreadCallbackEntry *next;
1245} SDL_MainThreadCallbackEntry;
1246
1247static SDL_Mutex *SDL_main_callbacks_lock;
1248static SDL_MainThreadCallbackEntry *SDL_main_callbacks_head;
1249static SDL_MainThreadCallbackEntry *SDL_main_callbacks_tail;
1250
1251static SDL_MainThreadCallbackEntry *SDL_CreateMainThreadCallback(SDL_MainThreadCallback callback, void *userdata, bool wait_complete)
1252{
1253 SDL_MainThreadCallbackEntry *entry = (SDL_MainThreadCallbackEntry *)SDL_malloc(sizeof(*entry));
1254 if (!entry) {
1255 return NULL;
1256 }
1257
1258 entry->callback = callback;
1259 entry->userdata = userdata;
1260 SDL_SetAtomicInt(&entry->state, SDL_MAIN_CALLBACK_WAITING);
1261 if (wait_complete) {
1262 entry->semaphore = SDL_CreateSemaphore(0);
1263 if (!entry->semaphore) {
1264 SDL_free(entry);
1265 return NULL;
1266 }
1267 } else {
1268 entry->semaphore = NULL;
1269 }
1270 entry->next = NULL;
1271
1272 return entry;
1273}
1274
1275static void SDL_DestroyMainThreadCallback(SDL_MainThreadCallbackEntry *entry)
1276{
1277 if (entry->semaphore) {
1278 SDL_DestroySemaphore(entry->semaphore);
1279 }
1280 SDL_free(entry);
1281}
1282
1283static void SDL_InitMainThreadCallbacks(void)
1284{
1285 SDL_main_callbacks_lock = SDL_CreateMutex();
1286 SDL_assert(SDL_main_callbacks_head == NULL &&
1287 SDL_main_callbacks_tail == NULL);
1288}
1289
1290static void SDL_QuitMainThreadCallbacks(void)
1291{
1292 SDL_MainThreadCallbackEntry *entry;
1293
1294 SDL_LockMutex(SDL_main_callbacks_lock);
1295 {
1296 entry = SDL_main_callbacks_head;
1297 SDL_main_callbacks_head = NULL;
1298 SDL_main_callbacks_tail = NULL;
1299 }
1300 SDL_UnlockMutex(SDL_main_callbacks_lock);
1301
1302 while (entry) {
1303 SDL_MainThreadCallbackEntry *next = entry->next;
1304
1305 if (entry->semaphore) {
1306 // Let the waiting thread know this is canceled
1307 SDL_SetAtomicInt(&entry->state, SDL_MAIN_CALLBACK_CANCELED);
1308 SDL_SignalSemaphore(entry->semaphore);
1309 } else {
1310 // Nobody's waiting for this, clean it up
1311 SDL_DestroyMainThreadCallback(entry);
1312 }
1313 entry = next;
1314 }
1315
1316 SDL_DestroyMutex(SDL_main_callbacks_lock);
1317 SDL_main_callbacks_lock = NULL;
1318}
1319
1320static void SDL_RunMainThreadCallbacks(void)
1321{
1322 SDL_MainThreadCallbackEntry *entry;
1323
1324 SDL_LockMutex(SDL_main_callbacks_lock);
1325 {
1326 entry = SDL_main_callbacks_head;
1327 SDL_main_callbacks_head = NULL;
1328 SDL_main_callbacks_tail = NULL;
1329 }
1330 SDL_UnlockMutex(SDL_main_callbacks_lock);
1331
1332 while (entry) {
1333 SDL_MainThreadCallbackEntry *next = entry->next;
1334
1335 entry->callback(entry->userdata);
1336
1337 if (entry->semaphore) {
1338 // Let the waiting thread know this is done
1339 SDL_SetAtomicInt(&entry->state, SDL_MAIN_CALLBACK_COMPLETE);
1340 SDL_SignalSemaphore(entry->semaphore);
1341 } else {
1342 // Nobody's waiting for this, clean it up
1343 SDL_DestroyMainThreadCallback(entry);
1344 }
1345 entry = next;
1346 }
1347}
1348
1349bool SDL_RunOnMainThread(SDL_MainThreadCallback callback, void *userdata, bool wait_complete)
1350{
1351 if (SDL_IsMainThread() || !SDL_WasInit(SDL_INIT_EVENTS)) {
1352 // No need to queue the callback
1353 callback(userdata);
1354 return true;
1355 }
1356
1357 SDL_MainThreadCallbackEntry *entry = SDL_CreateMainThreadCallback(callback, userdata, wait_complete);
1358 if (!entry) {
1359 return false;
1360 }
1361
1362 SDL_LockMutex(SDL_main_callbacks_lock);
1363 {
1364 if (SDL_main_callbacks_tail) {
1365 SDL_main_callbacks_tail->next = entry;
1366 SDL_main_callbacks_tail = entry;
1367 } else {
1368 SDL_main_callbacks_head = entry;
1369 SDL_main_callbacks_tail = entry;
1370 }
1371 }
1372 SDL_UnlockMutex(SDL_main_callbacks_lock);
1373
1374 // If the main thread is waiting for events, wake it up
1375 SDL_SendWakeupEvent();
1376
1377 if (!wait_complete) {
1378 // Queued for execution, wait not requested
1379 return true;
1380 }
1381
1382 // Maximum wait of 30 seconds to prevent deadlocking forever
1383 const Sint32 MAX_CALLBACK_WAIT = 30 * 1000;
1384 SDL_WaitSemaphoreTimeout(entry->semaphore, MAX_CALLBACK_WAIT);
1385
1386 switch (SDL_GetAtomicInt(&entry->state)) {
1387 case SDL_MAIN_CALLBACK_COMPLETE:
1388 // Execution complete!
1389 SDL_DestroyMainThreadCallback(entry);
1390 return true;
1391
1392 case SDL_MAIN_CALLBACK_CANCELED:
1393 // The callback was canceled on the main thread
1394 SDL_DestroyMainThreadCallback(entry);
1395 return SDL_SetError("Callback canceled");
1396
1397 default:
1398 // Probably hit a deadlock in the callback
1399 // We can't destroy the entry as the semaphore will be signaled
1400 // if it ever comes back, just leak it here.
1401 return SDL_SetError("Callback timed out");
1402 }
1403}
1404
1405void SDL_PumpEventMaintenance(void)
1406{
1407#ifndef SDL_AUDIO_DISABLED
1408 SDL_UpdateAudio();
1409#endif
1410
1411#ifndef SDL_CAMERA_DISABLED
1412 SDL_UpdateCamera();
1413#endif
1414
1415#ifndef SDL_SENSOR_DISABLED
1416 // Check for sensor state change
1417 if (SDL_update_sensors) {
1418 SDL_UpdateSensors();
1419 }
1420#endif
1421
1422#ifndef SDL_JOYSTICK_DISABLED
1423 // Check for joystick state change
1424 if (SDL_update_joysticks) {
1425 SDL_UpdateJoysticks();
1426 }
1427#endif
1428
1429 SDL_UpdateTrays();
1430
1431 SDL_SendPendingSignalEvents(); // in case we had a signal handler fire, etc.
1432}
1433
1434// Run the system dependent event loops
1435static void SDL_PumpEventsInternal(bool push_sentinel)
1436{
1437 // Free any temporary memory from old events
1438 SDL_FreeTemporaryMemory();
1439
1440 // Release any keys held down from last frame
1441 SDL_ReleaseAutoReleaseKeys();
1442
1443 // Run any pending main thread callbacks
1444 SDL_RunMainThreadCallbacks();
1445
1446#ifdef SDL_PLATFORM_ANDROID
1447 // Android event processing is independent of the video subsystem
1448 Android_PumpEvents(0);
1449#else
1450 // Get events from the video subsystem
1451 SDL_VideoDevice *_this = SDL_GetVideoDevice();
1452 if (_this) {
1453 _this->PumpEvents(_this);
1454 }
1455#endif
1456
1457 SDL_PumpEventMaintenance();
1458
1459 if (push_sentinel && SDL_EventEnabled(SDL_EVENT_POLL_SENTINEL)) {
1460 SDL_Event sentinel;
1461
1462 // Make sure we don't already have a sentinel in the queue, and add one to the end
1463 if (SDL_GetAtomicInt(&SDL_sentinel_pending) > 0) {
1464 SDL_PeepEventsInternal(&sentinel, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, true);
1465 }
1466
1467 sentinel.type = SDL_EVENT_POLL_SENTINEL;
1468 sentinel.common.timestamp = 0;
1469 SDL_PushEvent(&sentinel);
1470 }
1471}
1472
1473void SDL_PumpEvents(void)
1474{
1475 SDL_PumpEventsInternal(false);
1476}
1477
1478// Public functions
1479
1480bool SDL_PollEvent(SDL_Event *event)
1481{
1482 return SDL_WaitEventTimeoutNS(event, 0);
1483}
1484
1485#ifndef SDL_PLATFORM_ANDROID
1486
1487static Sint64 SDL_events_get_polling_interval(void)
1488{
1489 Sint64 poll_intervalNS = SDL_MAX_SINT64;
1490
1491#ifndef SDL_JOYSTICK_DISABLED
1492 if (SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks) {
1493 if (SDL_JoysticksOpened()) {
1494 // If we have joysticks open, we need to poll rapidly for events
1495 poll_intervalNS = SDL_min(poll_intervalNS, EVENT_POLL_INTERVAL_NS);
1496 } else {
1497 // If not, just poll every few seconds to enumerate new joysticks
1498 poll_intervalNS = SDL_min(poll_intervalNS, ENUMERATION_POLL_INTERVAL_NS);
1499 }
1500 }
1501#endif
1502
1503#ifndef SDL_SENSOR_DISABLED
1504 if (SDL_WasInit(SDL_INIT_SENSOR) && SDL_update_sensors && SDL_SensorsOpened()) {
1505 // If we have sensors open, we need to poll rapidly for events
1506 poll_intervalNS = SDL_min(poll_intervalNS, EVENT_POLL_INTERVAL_NS);
1507 }
1508#endif
1509
1510 return poll_intervalNS;
1511}
1512
1513static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeup_window, SDL_Event *event, Uint64 start, Sint64 timeoutNS)
1514{
1515 Sint64 loop_timeoutNS = timeoutNS;
1516 Sint64 poll_intervalNS = SDL_events_get_polling_interval();
1517
1518 for (;;) {
1519 int status;
1520 /* Pump events on entry and each time we wake to ensure:
1521 a) All pending events are batch processed after waking up from a wait
1522 b) Waiting can be completely skipped if events are already available to be pumped
1523 c) Periodic processing that takes place in some platform PumpEvents() functions happens
1524 d) Signals received in WaitEventTimeout() are turned into SDL events
1525 */
1526 SDL_PumpEventsInternal(true);
1527
1528 SDL_LockMutex(_this->wakeup_lock);
1529 {
1530 status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST);
1531 // If status == 0 we are going to block so wakeup will be needed.
1532 if (status == 0) {
1533 _this->wakeup_window = wakeup_window;
1534 } else {
1535 _this->wakeup_window = NULL;
1536 }
1537 }
1538 SDL_UnlockMutex(_this->wakeup_lock);
1539
1540 if (status < 0) {
1541 // Got an error: return
1542 break;
1543 }
1544 if (status > 0) {
1545 // There is an event, we can return.
1546 return 1;
1547 }
1548 // No events found in the queue, call WaitEventTimeout to wait for an event.
1549 if (timeoutNS > 0) {
1550 Sint64 elapsed = SDL_GetTicksNS() - start;
1551 if (elapsed >= timeoutNS) {
1552 // Set wakeup_window to NULL without holding the lock.
1553 _this->wakeup_window = NULL;
1554 return 0;
1555 }
1556 loop_timeoutNS = (timeoutNS - elapsed);
1557 }
1558 // Adjust the timeout for any polling requirements we currently have.
1559 if (poll_intervalNS != SDL_MAX_SINT64) {
1560 if (loop_timeoutNS >= 0) {
1561 loop_timeoutNS = SDL_min(loop_timeoutNS, poll_intervalNS);
1562 } else {
1563 loop_timeoutNS = poll_intervalNS;
1564 }
1565 }
1566 status = _this->WaitEventTimeout(_this, loop_timeoutNS);
1567 // Set wakeup_window to NULL without holding the lock.
1568 _this->wakeup_window = NULL;
1569 if (status == 0 && poll_intervalNS != SDL_MAX_SINT64 && loop_timeoutNS == poll_intervalNS) {
1570 // We may have woken up to poll. Try again
1571 continue;
1572 } else if (status <= 0) {
1573 // There is either an error or the timeout is elapsed: return
1574 return status;
1575 }
1576 /* An event was found and pumped into the SDL events queue. Continue the loop
1577 to let SDL_PeepEvents pick it up .*/
1578 }
1579 return 0;
1580}
1581
1582static SDL_Window *SDL_find_active_window(SDL_VideoDevice *_this)
1583{
1584 SDL_Window *window;
1585 for (window = _this->windows; window; window = window->next) {
1586 if (!window->is_destroying) {
1587 return window;
1588 }
1589 }
1590 return NULL;
1591}
1592
1593#endif // !SDL_PLATFORM_ANDROID
1594
1595bool SDL_WaitEvent(SDL_Event *event)
1596{
1597 return SDL_WaitEventTimeoutNS(event, -1);
1598}
1599
1600bool SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS)
1601{
1602 Sint64 timeoutNS;
1603
1604 if (timeoutMS > 0) {
1605 timeoutNS = SDL_MS_TO_NS(timeoutMS);
1606 } else {
1607 timeoutNS = timeoutMS;
1608 }
1609 return SDL_WaitEventTimeoutNS(event, timeoutNS);
1610}
1611
1612bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS)
1613{
1614 Uint64 start, expiration;
1615 bool include_sentinel = (timeoutNS == 0);
1616 int result;
1617
1618 if (timeoutNS > 0) {
1619 start = SDL_GetTicksNS();
1620 expiration = start + timeoutNS;
1621 } else {
1622 start = 0;
1623 expiration = 0;
1624 }
1625
1626 // If there isn't a poll sentinel event pending, pump events and add one
1627 if (SDL_GetAtomicInt(&SDL_sentinel_pending) == 0) {
1628 SDL_PumpEventsInternal(true);
1629 }
1630
1631 // First check for existing events
1632 result = SDL_PeepEventsInternal(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, include_sentinel);
1633 if (result < 0) {
1634 return false;
1635 }
1636 if (include_sentinel) {
1637 if (event) {
1638 if (event->type == SDL_EVENT_POLL_SENTINEL) {
1639 // Reached the end of a poll cycle, and not willing to wait
1640 return false;
1641 }
1642 } else {
1643 // Need to peek the next event to check for sentinel
1644 SDL_Event dummy;
1645
1646 if (SDL_PeepEventsInternal(&dummy, 1, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, true) &&
1647 dummy.type == SDL_EVENT_POLL_SENTINEL) {
1648 SDL_PeepEventsInternal(&dummy, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, true);
1649 // Reached the end of a poll cycle, and not willing to wait
1650 return false;
1651 }
1652 }
1653 }
1654 if (result == 0) {
1655 if (timeoutNS == 0) {
1656 // No events available, and not willing to wait
1657 return false;
1658 }
1659 } else {
1660 // Has existing events
1661 return true;
1662 }
1663 // We should have completely handled timeoutNS == 0 above
1664 SDL_assert(timeoutNS != 0);
1665
1666#ifdef SDL_PLATFORM_ANDROID
1667 for (;;) {
1668 if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) {
1669 return true;
1670 }
1671
1672 Uint64 delay = -1;
1673 if (timeoutNS > 0) {
1674 Uint64 now = SDL_GetTicksNS();
1675 if (now >= expiration) {
1676 // Timeout expired and no events
1677 return false;
1678 }
1679 delay = (expiration - now);
1680 }
1681 Android_PumpEvents(delay);
1682 }
1683#else
1684 SDL_VideoDevice *_this = SDL_GetVideoDevice();
1685 if (_this && _this->WaitEventTimeout && _this->SendWakeupEvent) {
1686 // Look if a shown window is available to send the wakeup event.
1687 SDL_Window *wakeup_window = SDL_find_active_window(_this);
1688 if (wakeup_window) {
1689 result = SDL_WaitEventTimeout_Device(_this, wakeup_window, event, start, timeoutNS);
1690 if (result > 0) {
1691 return true;
1692 } else if (result == 0) {
1693 return false;
1694 } else {
1695 /* There may be implementation-defined conditions where the backend cannot
1696 * reliably wait for the next event. If that happens, fall back to polling.
1697 */
1698 }
1699 }
1700 }
1701
1702 for (;;) {
1703 SDL_PumpEventsInternal(true);
1704
1705 if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) {
1706 return true;
1707 }
1708
1709 Uint64 delay = EVENT_POLL_INTERVAL_NS;
1710 if (timeoutNS > 0) {
1711 Uint64 now = SDL_GetTicksNS();
1712 if (now >= expiration) {
1713 // Timeout expired and no events
1714 return false;
1715 }
1716 delay = SDL_min((expiration - now), delay);
1717 }
1718 SDL_DelayNS(delay);
1719 }
1720#endif // SDL_PLATFORM_ANDROID
1721}
1722
1723static bool SDL_CallEventWatchers(SDL_Event *event)
1724{
1725 if (event->common.type == SDL_EVENT_POLL_SENTINEL) {
1726 return true;
1727 }
1728
1729 return SDL_DispatchEventWatchList(&SDL_event_watchers, event);
1730}
1731
1732bool SDL_PushEvent(SDL_Event *event)
1733{
1734 if (!event->common.timestamp) {
1735 event->common.timestamp = SDL_GetTicksNS();
1736 }
1737
1738 if (!SDL_CallEventWatchers(event)) {
1739 SDL_ClearError();
1740 return false;
1741 }
1742
1743 if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) {
1744 return false;
1745 }
1746
1747 return true;
1748}
1749
1750void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
1751{
1752 SDL_EventEntry *event, *next;
1753 SDL_LockMutex(SDL_event_watchers.lock);
1754 {
1755 // Set filter and discard pending events
1756 SDL_event_watchers.filter.callback = filter;
1757 SDL_event_watchers.filter.userdata = userdata;
1758 if (filter) {
1759 // Cut all events not accepted by the filter
1760 SDL_LockMutex(SDL_EventQ.lock);
1761 {
1762 for (event = SDL_EventQ.head; event; event = next) {
1763 next = event->next;
1764 if (!filter(userdata, &event->event)) {
1765 SDL_CutEvent(event);
1766 }
1767 }
1768 }
1769 SDL_UnlockMutex(SDL_EventQ.lock);
1770 }
1771 }
1772 SDL_UnlockMutex(SDL_event_watchers.lock);
1773}
1774
1775bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata)
1776{
1777 SDL_EventWatcher event_ok;
1778
1779 SDL_LockMutex(SDL_event_watchers.lock);
1780 {
1781 event_ok = SDL_event_watchers.filter;
1782 }
1783 SDL_UnlockMutex(SDL_event_watchers.lock);
1784
1785 if (filter) {
1786 *filter = event_ok.callback;
1787 }
1788 if (userdata) {
1789 *userdata = event_ok.userdata;
1790 }
1791 return event_ok.callback ? true : false;
1792}
1793
1794bool SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
1795{
1796 return SDL_AddEventWatchList(&SDL_event_watchers, filter, userdata);
1797}
1798
1799void SDL_RemoveEventWatch(SDL_EventFilter filter, void *userdata)
1800{
1801 SDL_RemoveEventWatchList(&SDL_event_watchers, filter, userdata);
1802}
1803
1804void SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
1805{
1806 SDL_LockMutex(SDL_EventQ.lock);
1807 {
1808 SDL_EventEntry *entry, *next;
1809 for (entry = SDL_EventQ.head; entry; entry = next) {
1810 next = entry->next;
1811 if (!filter(userdata, &entry->event)) {
1812 SDL_CutEvent(entry);
1813 }
1814 }
1815 }
1816 SDL_UnlockMutex(SDL_EventQ.lock);
1817}
1818
1819void SDL_SetEventEnabled(Uint32 type, bool enabled)
1820{
1821 bool current_state;
1822 Uint8 hi = ((type >> 8) & 0xff);
1823 Uint8 lo = (type & 0xff);
1824
1825 if (SDL_disabled_events[hi] &&
1826 (SDL_disabled_events[hi]->bits[lo / 32] & (1 << (lo & 31)))) {
1827 current_state = false;
1828 } else {
1829 current_state = true;
1830 }
1831
1832 if ((enabled != false) != current_state) {
1833 if (enabled) {
1834 SDL_assert(SDL_disabled_events[hi] != NULL);
1835 SDL_disabled_events[hi]->bits[lo / 32] &= ~(1 << (lo & 31));
1836
1837 // Gamepad events depend on joystick events
1838 switch (type) {
1839 case SDL_EVENT_GAMEPAD_ADDED:
1840 SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_ADDED, true);
1841 break;
1842 case SDL_EVENT_GAMEPAD_REMOVED:
1843 SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_REMOVED, true);
1844 break;
1845 case SDL_EVENT_GAMEPAD_AXIS_MOTION:
1846 case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
1847 case SDL_EVENT_GAMEPAD_BUTTON_UP:
1848 SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_AXIS_MOTION, true);
1849 SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_HAT_MOTION, true);
1850 SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_DOWN, true);
1851 SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_UP, true);
1852 break;
1853 case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE:
1854 SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE, true);
1855 break;
1856 default:
1857 break;
1858 }
1859 } else {
1860 // Disable this event type and discard pending events
1861 if (!SDL_disabled_events[hi]) {
1862 SDL_disabled_events[hi] = (SDL_DisabledEventBlock *)SDL_calloc(1, sizeof(SDL_DisabledEventBlock));
1863 }
1864 // Out of memory, nothing we can do...
1865 if (SDL_disabled_events[hi]) {
1866 SDL_disabled_events[hi]->bits[lo / 32] |= (1 << (lo & 31));
1867 SDL_FlushEvent(type);
1868 }
1869 }
1870
1871 /* turn off drag'n'drop support if we've disabled the events.
1872 This might change some UI details at the OS level. */
1873 if (type == SDL_EVENT_DROP_FILE || type == SDL_EVENT_DROP_TEXT) {
1874 SDL_ToggleDragAndDropSupport();
1875 }
1876 }
1877}
1878
1879bool SDL_EventEnabled(Uint32 type)
1880{
1881 Uint8 hi = ((type >> 8) & 0xff);
1882 Uint8 lo = (type & 0xff);
1883
1884 if (SDL_disabled_events[hi] &&
1885 (SDL_disabled_events[hi]->bits[lo / 32] & (1 << (lo & 31)))) {
1886 return false;
1887 } else {
1888 return true;
1889 }
1890}
1891
1892Uint32 SDL_RegisterEvents(int numevents)
1893{
1894 Uint32 event_base = 0;
1895
1896 if (numevents > 0) {
1897 int value = SDL_AddAtomicInt(&SDL_userevents, numevents);
1898 if (value >= 0 && value <= (SDL_EVENT_LAST - SDL_EVENT_USER)) {
1899 event_base = (Uint32)(SDL_EVENT_USER + value);
1900 }
1901 }
1902 return event_base;
1903}
1904
1905void SDL_SendAppEvent(SDL_EventType eventType)
1906{
1907 if (SDL_EventEnabled(eventType)) {
1908 SDL_Event event;
1909 event.type = eventType;
1910 event.common.timestamp = 0;
1911
1912 switch (eventType) {
1913 case SDL_EVENT_TERMINATING:
1914 case SDL_EVENT_LOW_MEMORY:
1915 case SDL_EVENT_WILL_ENTER_BACKGROUND:
1916 case SDL_EVENT_DID_ENTER_BACKGROUND:
1917 case SDL_EVENT_WILL_ENTER_FOREGROUND:
1918 case SDL_EVENT_DID_ENTER_FOREGROUND:
1919 // We won't actually queue this event, it needs to be handled in this call stack by an event watcher
1920 if (SDL_EventLoggingVerbosity > 0) {
1921 SDL_LogEvent(&event);
1922 }
1923 SDL_CallEventWatchers(&event);
1924 break;
1925 default:
1926 SDL_PushEvent(&event);
1927 break;
1928 }
1929 }
1930}
1931
1932void SDL_SendKeymapChangedEvent(void)
1933{
1934 SDL_SendAppEvent(SDL_EVENT_KEYMAP_CHANGED);
1935}
1936
1937void SDL_SendLocaleChangedEvent(void)
1938{
1939 SDL_SendAppEvent(SDL_EVENT_LOCALE_CHANGED);
1940}
1941
1942void SDL_SendSystemThemeChangedEvent(void)
1943{
1944 SDL_SendAppEvent(SDL_EVENT_SYSTEM_THEME_CHANGED);
1945}
1946
1947bool SDL_InitEvents(void)
1948{
1949#ifdef SDL_PLATFORM_ANDROID
1950 Android_InitEvents();
1951#endif
1952#ifndef SDL_JOYSTICK_DISABLED
1953 SDL_AddHintCallback(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_AutoUpdateJoysticksChanged, NULL);
1954#endif
1955#ifndef SDL_SENSOR_DISABLED
1956 SDL_AddHintCallback(SDL_HINT_AUTO_UPDATE_SENSORS, SDL_AutoUpdateSensorsChanged, NULL);
1957#endif
1958 SDL_AddHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
1959 SDL_AddHintCallback(SDL_HINT_POLL_SENTINEL, SDL_PollSentinelChanged, NULL);
1960 SDL_InitMainThreadCallbacks();
1961 if (!SDL_StartEventLoop()) {
1962 SDL_RemoveHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
1963 return false;
1964 }
1965
1966 SDL_InitQuit();
1967
1968 return true;
1969}
1970
1971void SDL_QuitEvents(void)
1972{
1973 SDL_QuitQuit();
1974 SDL_StopEventLoop();
1975 SDL_QuitMainThreadCallbacks();
1976 SDL_RemoveHintCallback(SDL_HINT_POLL_SENTINEL, SDL_PollSentinelChanged, NULL);
1977 SDL_RemoveHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
1978#ifndef SDL_JOYSTICK_DISABLED
1979 SDL_RemoveHintCallback(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_AutoUpdateJoysticksChanged, NULL);
1980#endif
1981#ifndef SDL_SENSOR_DISABLED
1982 SDL_RemoveHintCallback(SDL_HINT_AUTO_UPDATE_SENSORS, SDL_AutoUpdateSensorsChanged, NULL);
1983#endif
1984#ifdef SDL_PLATFORM_ANDROID
1985 Android_QuitEvents();
1986#endif
1987}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_events_c.h b/contrib/SDL-3.2.8/src/events/SDL_events_c.h
new file mode 100644
index 0000000..e56ac47
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_events_c.h
@@ -0,0 +1,66 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#ifndef SDL_events_c_h_
23#define SDL_events_c_h_
24
25#include "SDL_internal.h"
26
27// Useful functions and variables from SDL_events.c
28#include "../video/SDL_sysvideo.h"
29
30#include "SDL_clipboardevents_c.h"
31#include "SDL_displayevents_c.h"
32#include "SDL_dropevents_c.h"
33#include "SDL_keyboard_c.h"
34#include "SDL_mouse_c.h"
35#include "SDL_touch_c.h"
36#include "SDL_pen_c.h"
37#include "SDL_windowevents_c.h"
38
39// Start and stop the event processing loop
40extern bool SDL_StartEventLoop(void);
41extern void SDL_StopEventLoop(void);
42extern void SDL_QuitInterrupt(void);
43
44extern void SDL_SendAppEvent(SDL_EventType eventType);
45extern void SDL_SendKeymapChangedEvent(void);
46extern void SDL_SendLocaleChangedEvent(void);
47extern void SDL_SendSystemThemeChangedEvent(void);
48
49extern void *SDL_AllocateTemporaryMemory(size_t size);
50extern const char *SDL_CreateTemporaryString(const char *string);
51extern void *SDL_ClaimTemporaryMemory(const void *mem);
52extern void SDL_FreeTemporaryMemory(void);
53
54extern void SDL_PumpEventMaintenance(void);
55
56extern void SDL_SendQuit(void);
57
58extern bool SDL_InitEvents(void);
59extern void SDL_QuitEvents(void);
60
61extern void SDL_SendPendingSignalEvents(void);
62
63extern bool SDL_InitQuit(void);
64extern void SDL_QuitQuit(void);
65
66#endif // SDL_events_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_eventwatch.c b/contrib/SDL-3.2.8/src/events/SDL_eventwatch.c
new file mode 100644
index 0000000..08e7248
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_eventwatch.c
@@ -0,0 +1,143 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#include "SDL_eventwatch_c.h"
24
25
26bool SDL_InitEventWatchList(SDL_EventWatchList *list)
27{
28 if (list->lock == NULL) {
29 list->lock = SDL_CreateMutex();
30 if (list->lock == NULL) {
31 return false;
32 }
33 }
34 return true;
35}
36
37void SDL_QuitEventWatchList(SDL_EventWatchList *list)
38{
39 if (list->lock) {
40 SDL_DestroyMutex(list->lock);
41 list->lock = NULL;
42 }
43 if (list->watchers) {
44 SDL_free(list->watchers);
45 list->watchers = NULL;
46 list->count = 0;
47 }
48 SDL_zero(list->filter);
49}
50
51bool SDL_DispatchEventWatchList(SDL_EventWatchList *list, SDL_Event *event)
52{
53 SDL_EventWatcher *filter = &list->filter;
54
55 if (!filter->callback && list->count == 0) {
56 return true;
57 }
58
59 SDL_LockMutex(list->lock);
60 {
61 // Make sure we only dispatch the current watcher list
62 int i, count = list->count;
63
64 if (filter->callback && !filter->callback(filter->userdata, event)) {
65 SDL_UnlockMutex(list->lock);
66 return false;
67 }
68
69 list->dispatching = true;
70 for (i = 0; i < count; ++i) {
71 if (!list->watchers[i].removed) {
72 list->watchers[i].callback(list->watchers[i].userdata, event);
73 }
74 }
75 list->dispatching = false;
76
77 if (list->removed) {
78 for (i = list->count; i--;) {
79 if (list->watchers[i].removed) {
80 --list->count;
81 if (i < list->count) {
82 SDL_memmove(&list->watchers[i], &list->watchers[i + 1], (list->count - i) * sizeof(list->watchers[i]));
83 }
84 }
85 }
86 list->removed = false;
87 }
88 }
89 SDL_UnlockMutex(list->lock);
90
91 return true;
92}
93
94bool SDL_AddEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata)
95{
96 bool result = true;
97
98 SDL_LockMutex(list->lock);
99 {
100 SDL_EventWatcher *watchers;
101
102 watchers = (SDL_EventWatcher *)SDL_realloc(list->watchers, (list->count + 1) * sizeof(*watchers));
103 if (watchers) {
104 SDL_EventWatcher *watcher;
105
106 list->watchers = watchers;
107 watcher = &list->watchers[list->count];
108 watcher->callback = filter;
109 watcher->userdata = userdata;
110 watcher->removed = false;
111 ++list->count;
112 } else {
113 result = false;
114 }
115 }
116 SDL_UnlockMutex(list->lock);
117
118 return result;
119}
120
121void SDL_RemoveEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata)
122{
123 SDL_LockMutex(list->lock);
124 {
125 int i;
126
127 for (i = 0; i < list->count; ++i) {
128 if (list->watchers[i].callback == filter && list->watchers[i].userdata == userdata) {
129 if (list->dispatching) {
130 list->watchers[i].removed = true;
131 list->removed = true;
132 } else {
133 --list->count;
134 if (i < list->count) {
135 SDL_memmove(&list->watchers[i], &list->watchers[i + 1], (list->count - i) * sizeof(list->watchers[i]));
136 }
137 }
138 break;
139 }
140 }
141 }
142 SDL_UnlockMutex(list->lock);
143}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_eventwatch_c.h b/contrib/SDL-3.2.8/src/events/SDL_eventwatch_c.h
new file mode 100644
index 0000000..c9aea38
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_eventwatch_c.h
@@ -0,0 +1,45 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23typedef struct SDL_EventWatcher
24{
25 SDL_EventFilter callback;
26 void *userdata;
27 bool removed;
28} SDL_EventWatcher;
29
30typedef struct SDL_EventWatchList
31{
32 SDL_Mutex *lock;
33 SDL_EventWatcher filter;
34 SDL_EventWatcher *watchers;
35 int count;
36 bool dispatching;
37 bool removed;
38} SDL_EventWatchList;
39
40
41extern bool SDL_InitEventWatchList(SDL_EventWatchList *list);
42extern void SDL_QuitEventWatchList(SDL_EventWatchList *list);
43extern bool SDL_DispatchEventWatchList(SDL_EventWatchList *list, SDL_Event *event);
44extern bool SDL_AddEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata);
45extern void SDL_RemoveEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata);
diff --git a/contrib/SDL-3.2.8/src/events/SDL_keyboard.c b/contrib/SDL-3.2.8/src/events/SDL_keyboard.c
new file mode 100644
index 0000000..066c6e6
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_keyboard.c
@@ -0,0 +1,922 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// General keyboard handling code for SDL
24
25#include "SDL_events_c.h"
26#include "SDL_keymap_c.h"
27#include "../video/SDL_sysvideo.h"
28
29#if 0
30#define DEBUG_KEYBOARD
31#endif
32
33// Global keyboard information
34
35#define KEYBOARD_HARDWARE 0x01
36#define KEYBOARD_VIRTUAL 0x02
37#define KEYBOARD_AUTORELEASE 0x04
38#define KEYBOARD_IGNOREMODIFIERS 0x08
39
40#define KEYBOARD_SOURCE_MASK (KEYBOARD_HARDWARE | KEYBOARD_AUTORELEASE)
41
42#define KEYCODE_OPTION_HIDE_NUMPAD 0x01
43#define KEYCODE_OPTION_FRENCH_NUMBERS 0x02
44#define KEYCODE_OPTION_LATIN_LETTERS 0x04
45#define DEFAULT_KEYCODE_OPTIONS (KEYCODE_OPTION_FRENCH_NUMBERS | KEYCODE_OPTION_LATIN_LETTERS)
46
47typedef struct SDL_KeyboardInstance
48{
49 SDL_KeyboardID instance_id;
50 char *name;
51} SDL_KeyboardInstance;
52
53typedef struct SDL_Keyboard
54{
55 // Data common to all keyboards
56 SDL_Window *focus;
57 SDL_Keymod modstate;
58 Uint8 keysource[SDL_SCANCODE_COUNT];
59 bool keystate[SDL_SCANCODE_COUNT];
60 SDL_Keymap *keymap;
61 bool french_numbers;
62 bool latin_letters;
63 bool thai_keyboard;
64 Uint32 keycode_options;
65 bool autorelease_pending;
66 Uint64 hardware_timestamp;
67 int next_reserved_scancode;
68} SDL_Keyboard;
69
70static SDL_Keyboard SDL_keyboard;
71static int SDL_keyboard_count;
72static SDL_KeyboardInstance *SDL_keyboards;
73
74static void SDLCALL SDL_KeycodeOptionsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
75{
76 SDL_Keyboard *keyboard = (SDL_Keyboard *)userdata;
77
78 if (hint && *hint) {
79 keyboard->keycode_options = 0;
80 if (!SDL_strstr(hint, "none")) {
81 if (SDL_strstr(hint, "hide_numpad")) {
82 keyboard->keycode_options |= KEYCODE_OPTION_HIDE_NUMPAD;
83 }
84 if (SDL_strstr(hint, "french_numbers")) {
85 keyboard->keycode_options |= KEYCODE_OPTION_FRENCH_NUMBERS;
86 }
87 if (SDL_strstr(hint, "latin_letters")) {
88 keyboard->keycode_options |= KEYCODE_OPTION_LATIN_LETTERS;
89 }
90 }
91 } else {
92 keyboard->keycode_options = DEFAULT_KEYCODE_OPTIONS;
93 }
94}
95
96// Public functions
97bool SDL_InitKeyboard(void)
98{
99 SDL_AddHintCallback(SDL_HINT_KEYCODE_OPTIONS,
100 SDL_KeycodeOptionsChanged, &SDL_keyboard);
101 return true;
102}
103
104bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys)
105{
106 const int REAL_KEYBOARD_KEY_COUNT = 50;
107 if (num_keys > 0 && num_keys < REAL_KEYBOARD_KEY_COUNT) {
108 return false;
109 }
110
111 // Eventually we'll have a blacklist of devices that enumerate as keyboards but aren't really
112 return true;
113}
114
115static int SDL_GetKeyboardIndex(SDL_KeyboardID keyboardID)
116{
117 for (int i = 0; i < SDL_keyboard_count; ++i) {
118 if (keyboardID == SDL_keyboards[i].instance_id) {
119 return i;
120 }
121 }
122 return -1;
123}
124
125void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name, bool send_event)
126{
127 int keyboard_index = SDL_GetKeyboardIndex(keyboardID);
128 if (keyboard_index >= 0) {
129 // We already know about this keyboard
130 return;
131 }
132
133 SDL_assert(keyboardID != 0);
134
135 SDL_KeyboardInstance *keyboards = (SDL_KeyboardInstance *)SDL_realloc(SDL_keyboards, (SDL_keyboard_count + 1) * sizeof(*keyboards));
136 if (!keyboards) {
137 return;
138 }
139 SDL_KeyboardInstance *instance = &keyboards[SDL_keyboard_count];
140 instance->instance_id = keyboardID;
141 instance->name = SDL_strdup(name ? name : "");
142 SDL_keyboards = keyboards;
143 ++SDL_keyboard_count;
144
145 if (send_event) {
146 SDL_Event event;
147 SDL_zero(event);
148 event.type = SDL_EVENT_KEYBOARD_ADDED;
149 event.kdevice.which = keyboardID;
150 SDL_PushEvent(&event);
151 }
152}
153
154void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID, bool send_event)
155{
156 int keyboard_index = SDL_GetKeyboardIndex(keyboardID);
157 if (keyboard_index < 0) {
158 // We don't know about this keyboard
159 return;
160 }
161
162 SDL_free(SDL_keyboards[keyboard_index].name);
163
164 if (keyboard_index != SDL_keyboard_count - 1) {
165 SDL_memmove(&SDL_keyboards[keyboard_index], &SDL_keyboards[keyboard_index + 1], (SDL_keyboard_count - keyboard_index - 1) * sizeof(SDL_keyboards[keyboard_index]));
166 }
167 --SDL_keyboard_count;
168
169 if (send_event) {
170 SDL_Event event;
171 SDL_zero(event);
172 event.type = SDL_EVENT_KEYBOARD_REMOVED;
173 event.kdevice.which = keyboardID;
174 SDL_PushEvent(&event);
175 }
176}
177
178bool SDL_HasKeyboard(void)
179{
180 return (SDL_keyboard_count > 0);
181}
182
183SDL_KeyboardID *SDL_GetKeyboards(int *count)
184{
185 int i;
186 SDL_KeyboardID *keyboards;
187
188 keyboards = (SDL_JoystickID *)SDL_malloc((SDL_keyboard_count + 1) * sizeof(*keyboards));
189 if (keyboards) {
190 if (count) {
191 *count = SDL_keyboard_count;
192 }
193
194 for (i = 0; i < SDL_keyboard_count; ++i) {
195 keyboards[i] = SDL_keyboards[i].instance_id;
196 }
197 keyboards[i] = 0;
198 } else {
199 if (count) {
200 *count = 0;
201 }
202 }
203
204 return keyboards;
205}
206
207const char *SDL_GetKeyboardNameForID(SDL_KeyboardID instance_id)
208{
209 int keyboard_index = SDL_GetKeyboardIndex(instance_id);
210 if (keyboard_index < 0) {
211 SDL_SetError("Keyboard %" SDL_PRIu32 " not found", instance_id);
212 return NULL;
213 }
214 return SDL_GetPersistentString(SDL_keyboards[keyboard_index].name);
215}
216
217void SDL_ResetKeyboard(void)
218{
219 SDL_Keyboard *keyboard = &SDL_keyboard;
220 int scancode;
221
222#ifdef DEBUG_KEYBOARD
223 SDL_Log("Resetting keyboard");
224#endif
225 for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_SCANCODE_COUNT; ++scancode) {
226 if (keyboard->keystate[scancode]) {
227 SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, 0, (SDL_Scancode)scancode, false);
228 }
229 }
230}
231
232SDL_Keymap *SDL_GetCurrentKeymap(void)
233{
234 SDL_Keyboard *keyboard = &SDL_keyboard;
235
236 if (keyboard->thai_keyboard) {
237 // Thai keyboards are QWERTY plus Thai characters, use the default QWERTY keymap
238 return NULL;
239 }
240
241 if ((keyboard->keycode_options & KEYCODE_OPTION_LATIN_LETTERS) &&
242 !keyboard->latin_letters) {
243 // We'll use the default QWERTY keymap
244 return NULL;
245 }
246
247 return keyboard->keymap;
248}
249
250void SDL_SetKeymap(SDL_Keymap *keymap, bool send_event)
251{
252 SDL_Keyboard *keyboard = &SDL_keyboard;
253
254 if (keyboard->keymap) {
255 SDL_DestroyKeymap(keyboard->keymap);
256 }
257
258 keyboard->keymap = keymap;
259
260 // Detect French number row (all symbols)
261 keyboard->french_numbers = true;
262 for (int i = SDL_SCANCODE_1; i <= SDL_SCANCODE_0; ++i) {
263 if (SDL_isdigit(SDL_GetKeymapKeycode(keymap, (SDL_Scancode)i, SDL_KMOD_NONE)) ||
264 !SDL_isdigit(SDL_GetKeymapKeycode(keymap, (SDL_Scancode)i, SDL_KMOD_SHIFT))) {
265 keyboard->french_numbers = false;
266 break;
267 }
268 }
269
270 // Detect non-Latin keymap
271 keyboard->thai_keyboard = false;
272 keyboard->latin_letters = false;
273 for (int i = SDL_SCANCODE_A; i <= SDL_SCANCODE_D; ++i) {
274 SDL_Keycode key = SDL_GetKeymapKeycode(keymap, (SDL_Scancode)i, SDL_KMOD_NONE);
275 if (key <= 0xFF) {
276 keyboard->latin_letters = true;
277 break;
278 }
279
280 if (key >= 0x0E00 && key <= 0x0E7F) {
281 keyboard->thai_keyboard = true;
282 break;
283 }
284 }
285
286 if (send_event) {
287 SDL_SendKeymapChangedEvent();
288 }
289}
290
291static SDL_Scancode GetNextReservedScancode(void)
292{
293 SDL_Keyboard *keyboard = &SDL_keyboard;
294 SDL_Scancode scancode;
295
296 if (keyboard->next_reserved_scancode && keyboard->next_reserved_scancode < SDL_SCANCODE_RESERVED + 100) {
297 scancode = (SDL_Scancode)keyboard->next_reserved_scancode;
298 } else {
299 scancode = SDL_SCANCODE_RESERVED;
300 }
301 keyboard->next_reserved_scancode = (int)scancode + 1;
302
303 return scancode;
304}
305
306static void SetKeymapEntry(SDL_Scancode scancode, SDL_Keymod modstate, SDL_Keycode keycode)
307{
308 SDL_Keyboard *keyboard = &SDL_keyboard;
309
310 if (!keyboard->keymap) {
311 keyboard->keymap = SDL_CreateKeymap();
312 }
313
314 SDL_SetKeymapEntry(keyboard->keymap, scancode, modstate, keycode);
315}
316
317SDL_Window *SDL_GetKeyboardFocus(void)
318{
319 SDL_Keyboard *keyboard = &SDL_keyboard;
320
321 return keyboard->focus;
322}
323
324bool SDL_SetKeyboardFocus(SDL_Window *window)
325{
326 SDL_VideoDevice *video = SDL_GetVideoDevice();
327 SDL_Keyboard *keyboard = &SDL_keyboard;
328 SDL_Mouse *mouse = SDL_GetMouse();
329
330 if (window) {
331 if (!SDL_ObjectValid(window, SDL_OBJECT_TYPE_WINDOW) || window->is_destroying) {
332 return SDL_SetError("Invalid window");
333 }
334 }
335
336 if (keyboard->focus && !window) {
337 // We won't get anymore keyboard messages, so reset keyboard state
338 SDL_ResetKeyboard();
339
340 // Also leave mouse relative mode
341 if (mouse->relative_mode) {
342 SDL_SetRelativeMouseMode(false);
343
344 SDL_Window *focus = keyboard->focus;
345 if ((focus->flags & SDL_WINDOW_MINIMIZED) != 0) {
346 // We can't warp the mouse within minimized windows, so manually restore the position
347 float x = focus->x + mouse->x;
348 float y = focus->y + mouse->y;
349 SDL_WarpMouseGlobal(x, y);
350 }
351 }
352 }
353
354 // See if the current window has lost focus
355 if (keyboard->focus && keyboard->focus != window) {
356 SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_LOST, 0, 0);
357
358 // Ensures IME compositions are committed
359 if (SDL_TextInputActive(keyboard->focus)) {
360 if (video && video->StopTextInput) {
361 video->StopTextInput(video, keyboard->focus);
362 }
363 }
364 }
365
366 keyboard->focus = window;
367
368 if (keyboard->focus) {
369 SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_GAINED, 0, 0);
370
371 if (SDL_TextInputActive(keyboard->focus)) {
372 if (video && video->StartTextInput) {
373 video->StartTextInput(video, keyboard->focus, keyboard->focus->text_input_props);
374 }
375 }
376 }
377
378 SDL_UpdateRelativeMouseMode();
379
380 return true;
381}
382
383static SDL_Keycode SDL_ConvertNumpadKeycode(SDL_Keycode keycode, bool numlock)
384{
385 switch (keycode) {
386 case SDLK_KP_DIVIDE:
387 return SDLK_SLASH;
388 case SDLK_KP_MULTIPLY:
389 return SDLK_ASTERISK;
390 case SDLK_KP_MINUS:
391 return SDLK_MINUS;
392 case SDLK_KP_PLUS:
393 return SDLK_PLUS;
394 case SDLK_KP_ENTER:
395 return SDLK_RETURN;
396 case SDLK_KP_1:
397 return numlock ? SDLK_1 : SDLK_END;
398 case SDLK_KP_2:
399 return numlock ? SDLK_2 : SDLK_DOWN;
400 case SDLK_KP_3:
401 return numlock ? SDLK_3 : SDLK_PAGEDOWN;
402 case SDLK_KP_4:
403 return numlock ? SDLK_4 : SDLK_LEFT;
404 case SDLK_KP_5:
405 return numlock ? SDLK_5 : SDLK_CLEAR;
406 case SDLK_KP_6:
407 return numlock ? SDLK_6 : SDLK_RIGHT;
408 case SDLK_KP_7:
409 return numlock ? SDLK_7 : SDLK_HOME;
410 case SDLK_KP_8:
411 return numlock ? SDLK_8 : SDLK_UP;
412 case SDLK_KP_9:
413 return numlock ? SDLK_9 : SDLK_PAGEUP;
414 case SDLK_KP_0:
415 return numlock ? SDLK_0 : SDLK_INSERT;
416 case SDLK_KP_PERIOD:
417 return numlock ? SDLK_PERIOD : SDLK_DELETE;
418 case SDLK_KP_EQUALS:
419 return SDLK_EQUALS;
420 case SDLK_KP_COMMA:
421 return SDLK_COMMA;
422 case SDLK_KP_EQUALSAS400:
423 return SDLK_EQUALS;
424 case SDLK_KP_LEFTPAREN:
425 return SDLK_LEFTPAREN;
426 case SDLK_KP_RIGHTPAREN:
427 return SDLK_RIGHTPAREN;
428 case SDLK_KP_LEFTBRACE:
429 return SDLK_LEFTBRACE;
430 case SDLK_KP_RIGHTBRACE:
431 return SDLK_RIGHTBRACE;
432 case SDLK_KP_TAB:
433 return SDLK_TAB;
434 case SDLK_KP_BACKSPACE:
435 return SDLK_BACKSPACE;
436 case SDLK_KP_A:
437 return SDLK_A;
438 case SDLK_KP_B:
439 return SDLK_B;
440 case SDLK_KP_C:
441 return SDLK_C;
442 case SDLK_KP_D:
443 return SDLK_D;
444 case SDLK_KP_E:
445 return SDLK_E;
446 case SDLK_KP_F:
447 return SDLK_F;
448 case SDLK_KP_PERCENT:
449 return SDLK_PERCENT;
450 case SDLK_KP_LESS:
451 return SDLK_LESS;
452 case SDLK_KP_GREATER:
453 return SDLK_GREATER;
454 case SDLK_KP_AMPERSAND:
455 return SDLK_AMPERSAND;
456 case SDLK_KP_COLON:
457 return SDLK_COLON;
458 case SDLK_KP_HASH:
459 return SDLK_HASH;
460 case SDLK_KP_SPACE:
461 return SDLK_SPACE;
462 case SDLK_KP_AT:
463 return SDLK_AT;
464 case SDLK_KP_EXCLAM:
465 return SDLK_EXCLAIM;
466 case SDLK_KP_PLUSMINUS:
467 return SDLK_PLUSMINUS;
468 default:
469 return keycode;
470 }
471}
472
473SDL_Keycode SDL_GetKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate, bool key_event)
474{
475 SDL_Keyboard *keyboard = &SDL_keyboard;
476
477 if (key_event) {
478 SDL_Keymap *keymap = SDL_GetCurrentKeymap();
479 bool numlock = (modstate & SDL_KMOD_NUM) != 0;
480 SDL_Keycode keycode;
481
482 // We won't be applying any modifiers by default
483 modstate = SDL_KMOD_NONE;
484
485 if ((keyboard->keycode_options & KEYCODE_OPTION_FRENCH_NUMBERS) &&
486 keyboard->french_numbers &&
487 (scancode >= SDL_SCANCODE_1 && scancode <= SDL_SCANCODE_0)) {
488 // Add the shift state to generate a numeric keycode
489 modstate |= SDL_KMOD_SHIFT;
490 }
491
492 keycode = SDL_GetKeymapKeycode(keymap, scancode, modstate);
493
494 if (keyboard->keycode_options & KEYCODE_OPTION_HIDE_NUMPAD) {
495 keycode = SDL_ConvertNumpadKeycode(keycode, numlock);
496 }
497 return keycode;
498 }
499
500 return SDL_GetKeymapKeycode(keyboard->keymap, scancode, modstate);
501}
502
503SDL_Scancode SDL_GetScancodeFromKey(SDL_Keycode key, SDL_Keymod *modstate)
504{
505 SDL_Keyboard *keyboard = &SDL_keyboard;
506
507 return SDL_GetKeymapScancode(keyboard->keymap, key, modstate);
508}
509
510static bool SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down)
511{
512 SDL_Keyboard *keyboard = &SDL_keyboard;
513 bool posted = false;
514 SDL_Keycode keycode = SDLK_UNKNOWN;
515 Uint32 type;
516 bool repeat = false;
517 const Uint8 source = flags & KEYBOARD_SOURCE_MASK;
518
519#ifdef DEBUG_KEYBOARD
520 SDL_Log("The '%s' key has been %s", SDL_GetScancodeName(scancode), down ? "pressed" : "released");
521#endif
522
523 // Figure out what type of event this is
524 if (down) {
525 type = SDL_EVENT_KEY_DOWN;
526 } else {
527 type = SDL_EVENT_KEY_UP;
528 }
529
530 if (scancode > SDL_SCANCODE_UNKNOWN && scancode < SDL_SCANCODE_COUNT) {
531 // Drop events that don't change state
532 if (down) {
533 if (keyboard->keystate[scancode]) {
534 if (!(keyboard->keysource[scancode] & source)) {
535 keyboard->keysource[scancode] |= source;
536 return false;
537 }
538 repeat = true;
539 }
540 keyboard->keysource[scancode] |= source;
541 } else {
542 if (!keyboard->keystate[scancode]) {
543 return false;
544 }
545 keyboard->keysource[scancode] = 0;
546 }
547
548 // Update internal keyboard state
549 keyboard->keystate[scancode] = down;
550
551 keycode = SDL_GetKeyFromScancode(scancode, keyboard->modstate, true);
552
553 } else if (rawcode == 0) {
554 // Nothing to do!
555 return false;
556 }
557
558 if (source == KEYBOARD_HARDWARE) {
559 keyboard->hardware_timestamp = SDL_GetTicks();
560 } else if (source == KEYBOARD_AUTORELEASE) {
561 keyboard->autorelease_pending = true;
562 }
563
564 // Update modifiers state if applicable
565 if (!(flags & KEYBOARD_IGNOREMODIFIERS) && !repeat) {
566 SDL_Keymod modifier;
567
568 switch (keycode) {
569 case SDLK_LCTRL:
570 modifier = SDL_KMOD_LCTRL;
571 break;
572 case SDLK_RCTRL:
573 modifier = SDL_KMOD_RCTRL;
574 break;
575 case SDLK_LSHIFT:
576 modifier = SDL_KMOD_LSHIFT;
577 break;
578 case SDLK_RSHIFT:
579 modifier = SDL_KMOD_RSHIFT;
580 break;
581 case SDLK_LALT:
582 modifier = SDL_KMOD_LALT;
583 break;
584 case SDLK_RALT:
585 modifier = SDL_KMOD_RALT;
586 break;
587 case SDLK_LGUI:
588 modifier = SDL_KMOD_LGUI;
589 break;
590 case SDLK_RGUI:
591 modifier = SDL_KMOD_RGUI;
592 break;
593 case SDLK_MODE:
594 modifier = SDL_KMOD_MODE;
595 break;
596 default:
597 modifier = SDL_KMOD_NONE;
598 break;
599 }
600 if (SDL_EVENT_KEY_DOWN == type) {
601 switch (keycode) {
602 case SDLK_NUMLOCKCLEAR:
603 keyboard->modstate ^= SDL_KMOD_NUM;
604 break;
605 case SDLK_CAPSLOCK:
606 keyboard->modstate ^= SDL_KMOD_CAPS;
607 break;
608 case SDLK_SCROLLLOCK:
609 keyboard->modstate ^= SDL_KMOD_SCROLL;
610 break;
611 default:
612 keyboard->modstate |= modifier;
613 break;
614 }
615 } else {
616 keyboard->modstate &= ~modifier;
617 }
618 }
619
620 // Post the event, if desired
621 if (SDL_EventEnabled(type)) {
622 SDL_Event event;
623 event.type = type;
624 event.common.timestamp = timestamp;
625 event.key.scancode = scancode;
626 event.key.key = keycode;
627 event.key.mod = keyboard->modstate;
628 event.key.raw = (Uint16)rawcode;
629 event.key.down = down;
630 event.key.repeat = repeat;
631 event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
632 event.key.which = keyboardID;
633 posted = SDL_PushEvent(&event);
634 }
635
636 /* If the keyboard is grabbed and the grabbed window is in full-screen,
637 minimize the window when we receive Alt+Tab, unless the application
638 has explicitly opted out of this behavior. */
639 if (keycode == SDLK_TAB && down &&
640 (keyboard->modstate & SDL_KMOD_ALT) &&
641 keyboard->focus &&
642 (keyboard->focus->flags & SDL_WINDOW_KEYBOARD_GRABBED) &&
643 (keyboard->focus->flags & SDL_WINDOW_FULLSCREEN) &&
644 SDL_GetHintBoolean(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, true)) {
645 /* We will temporarily forfeit our grab by minimizing our window,
646 allowing the user to escape the application */
647 SDL_MinimizeWindow(keyboard->focus);
648 }
649
650 return posted;
651}
652
653void SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch)
654{
655 SDL_Keyboard *keyboard = &SDL_keyboard;
656 SDL_Keymod modstate = SDL_KMOD_NONE;
657 SDL_Scancode scancode;
658
659 if (ch == '\n') {
660 ch = SDLK_RETURN;
661 }
662 scancode = SDL_GetKeymapScancode(keyboard->keymap, ch, &modstate);
663
664 // Make sure we have this keycode in our keymap
665 if (scancode == SDL_SCANCODE_UNKNOWN && ch < SDLK_SCANCODE_MASK) {
666 scancode = GetNextReservedScancode();
667 SetKeymapEntry(scancode, modstate, ch);
668 }
669
670 if (modstate & SDL_KMOD_SHIFT) {
671 // If the character uses shift, press shift down
672 SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, 0, SDL_SCANCODE_LSHIFT, true);
673 }
674
675 // Send a keydown and keyup for the character
676 SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, 0, scancode, true);
677 SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, 0, scancode, false);
678
679 if (modstate & SDL_KMOD_SHIFT) {
680 // If the character uses shift, release shift
681 SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, 0, SDL_SCANCODE_LSHIFT, false);
682 }
683}
684
685bool SDL_SendKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down)
686{
687 return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, rawcode, scancode, down);
688}
689
690bool SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, SDL_Keycode keycode, bool down)
691{
692 if (down) {
693 // Make sure we have this keycode in our keymap
694 SetKeymapEntry(scancode, SDL_GetModState(), keycode);
695 }
696
697 return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, rawcode, scancode, down);
698}
699
700bool SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down)
701{
702 return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE | KEYBOARD_IGNOREMODIFIERS, keyboardID, rawcode, scancode, down);
703}
704
705bool SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode)
706{
707 return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, 0, scancode, true);
708}
709
710void SDL_ReleaseAutoReleaseKeys(void)
711{
712 SDL_Keyboard *keyboard = &SDL_keyboard;
713 int scancode;
714
715 if (keyboard->autorelease_pending) {
716 for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_SCANCODE_COUNT; ++scancode) {
717 if (keyboard->keysource[scancode] == KEYBOARD_AUTORELEASE) {
718 SDL_SendKeyboardKeyInternal(0, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, 0, (SDL_Scancode)scancode, false);
719 }
720 }
721 keyboard->autorelease_pending = false;
722 }
723
724 if (keyboard->hardware_timestamp) {
725 // Keep hardware keyboard "active" for 250 ms
726 if (SDL_GetTicks() >= keyboard->hardware_timestamp + 250) {
727 keyboard->hardware_timestamp = 0;
728 }
729 }
730}
731
732bool SDL_HardwareKeyboardKeyPressed(void)
733{
734 SDL_Keyboard *keyboard = &SDL_keyboard;
735 int scancode;
736
737 for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_SCANCODE_COUNT; ++scancode) {
738 if (keyboard->keysource[scancode] & KEYBOARD_HARDWARE) {
739 return true;
740 }
741 }
742
743 return keyboard->hardware_timestamp ? true : false;
744}
745
746void SDL_SendKeyboardText(const char *text)
747{
748 SDL_Keyboard *keyboard = &SDL_keyboard;
749
750 if (!SDL_TextInputActive(keyboard->focus)) {
751 return;
752 }
753
754 if (!text || !*text) {
755 return;
756 }
757
758 // Don't post text events for unprintable characters
759 if (SDL_iscntrl((unsigned char)*text)) {
760 return;
761 }
762
763 // Post the event, if desired
764 if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) {
765 SDL_Event event;
766 event.type = SDL_EVENT_TEXT_INPUT;
767 event.common.timestamp = 0;
768 event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
769 event.text.text = SDL_CreateTemporaryString(text);
770 if (!event.text.text) {
771 return;
772 }
773 SDL_PushEvent(&event);
774 }
775}
776
777void SDL_SendEditingText(const char *text, int start, int length)
778{
779 SDL_Keyboard *keyboard = &SDL_keyboard;
780
781 if (!SDL_TextInputActive(keyboard->focus)) {
782 return;
783 }
784
785 if (!text) {
786 return;
787 }
788
789 // Post the event, if desired
790 if (SDL_EventEnabled(SDL_EVENT_TEXT_EDITING)) {
791 SDL_Event event;
792
793 event.type = SDL_EVENT_TEXT_EDITING;
794 event.common.timestamp = 0;
795 event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
796 event.edit.start = start;
797 event.edit.length = length;
798 event.edit.text = SDL_CreateTemporaryString(text);
799 if (!event.edit.text) {
800 return;
801 }
802 SDL_PushEvent(&event);
803 }
804}
805
806static const char * const *CreateCandidatesForEvent(char **candidates, int num_candidates)
807{
808 const char **event_candidates;
809 int i;
810 char *ptr;
811 size_t total_length = (num_candidates + 1) * sizeof(*event_candidates);
812
813 for (i = 0; i < num_candidates; ++i) {
814 size_t length = SDL_strlen(candidates[i]) + 1;
815
816 total_length += length;
817 }
818
819 event_candidates = (const char **)SDL_AllocateTemporaryMemory(total_length);
820 if (!event_candidates) {
821 return NULL;
822 }
823 ptr = (char *)(event_candidates + (num_candidates + 1));
824
825 for (i = 0; i < num_candidates; ++i) {
826 size_t length = SDL_strlen(candidates[i]) + 1;
827
828 event_candidates[i] = ptr;
829 SDL_memcpy(ptr, candidates[i], length);
830 ptr += length;
831 }
832 event_candidates[i] = NULL;
833
834 return event_candidates;
835}
836
837void SDL_SendEditingTextCandidates(char **candidates, int num_candidates, int selected_candidate, bool horizontal)
838{
839 SDL_Keyboard *keyboard = &SDL_keyboard;
840
841 if (!SDL_TextInputActive(keyboard->focus)) {
842 return;
843 }
844
845 // Post the event, if desired
846 if (SDL_EventEnabled(SDL_EVENT_TEXT_EDITING_CANDIDATES)) {
847 SDL_Event event;
848
849 event.type = SDL_EVENT_TEXT_EDITING_CANDIDATES;
850 event.common.timestamp = 0;
851 event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
852 if (num_candidates > 0) {
853 const char * const *event_candidates = CreateCandidatesForEvent(candidates, num_candidates);
854 if (!event_candidates) {
855 return;
856 }
857 event.edit_candidates.candidates = event_candidates;
858 event.edit_candidates.num_candidates = num_candidates;
859 event.edit_candidates.selected_candidate = selected_candidate;
860 event.edit_candidates.horizontal = horizontal;
861 } else {
862 event.edit_candidates.candidates = NULL;
863 event.edit_candidates.num_candidates = 0;
864 event.edit_candidates.selected_candidate = -1;
865 event.edit_candidates.horizontal = false;
866 }
867 SDL_PushEvent(&event);
868 }
869}
870
871void SDL_QuitKeyboard(void)
872{
873 for (int i = SDL_keyboard_count; i--;) {
874 SDL_RemoveKeyboard(SDL_keyboards[i].instance_id, false);
875 }
876 SDL_free(SDL_keyboards);
877 SDL_keyboards = NULL;
878
879 if (SDL_keyboard.keymap) {
880 SDL_DestroyKeymap(SDL_keyboard.keymap);
881 SDL_keyboard.keymap = NULL;
882 }
883
884 SDL_RemoveHintCallback(SDL_HINT_KEYCODE_OPTIONS,
885 SDL_KeycodeOptionsChanged, &SDL_keyboard);
886}
887
888const bool *SDL_GetKeyboardState(int *numkeys)
889{
890 SDL_Keyboard *keyboard = &SDL_keyboard;
891
892 if (numkeys != (int *)0) {
893 *numkeys = SDL_SCANCODE_COUNT;
894 }
895 return keyboard->keystate;
896}
897
898SDL_Keymod SDL_GetModState(void)
899{
900 SDL_Keyboard *keyboard = &SDL_keyboard;
901
902 return keyboard->modstate;
903}
904
905void SDL_SetModState(SDL_Keymod modstate)
906{
907 SDL_Keyboard *keyboard = &SDL_keyboard;
908
909 keyboard->modstate = modstate;
910}
911
912// Note that SDL_ToggleModState() is not a public API. SDL_SetModState() is.
913void SDL_ToggleModState(SDL_Keymod modstate, bool toggle)
914{
915 SDL_Keyboard *keyboard = &SDL_keyboard;
916 if (toggle) {
917 keyboard->modstate |= modstate;
918 } else {
919 keyboard->modstate &= ~modstate;
920 }
921}
922
diff --git a/contrib/SDL-3.2.8/src/events/SDL_keyboard_c.h b/contrib/SDL-3.2.8/src/events/SDL_keyboard_c.h
new file mode 100644
index 0000000..ddfb5c5
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_keyboard_c.h
@@ -0,0 +1,87 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_keyboard_c_h_
24#define SDL_keyboard_c_h_
25
26#include "SDL_keymap_c.h"
27
28// Keyboard events not associated with a specific input device
29#define SDL_GLOBAL_KEYBOARD_ID 0
30
31// The default keyboard input device, for platforms that don't have multiple keyboards
32#define SDL_DEFAULT_KEYBOARD_ID 1
33
34// Initialize the keyboard subsystem
35extern bool SDL_InitKeyboard(void);
36
37// Return whether a device is actually a keyboard
38extern bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys);
39
40// A keyboard has been added to the system
41extern void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name, bool send_event);
42
43// A keyboard has been removed from the system
44extern void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID, bool send_event);
45
46// Set the mapping of scancode to key codes
47extern void SDL_SetKeymap(SDL_Keymap *keymap, bool send_event);
48
49// Set the keyboard focus window
50extern bool SDL_SetKeyboardFocus(SDL_Window *window);
51
52/* Send a character from an on-screen keyboard as scancode and modifier key events,
53 currently assuming ASCII characters on a US keyboard layout
54 */
55extern void SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch);
56
57// Send a keyboard key event
58extern bool SDL_SendKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down);
59extern bool SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down);
60extern bool SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode);
61
62/* This is for platforms that don't know the keymap but can report scancode and keycode directly.
63 Most platforms should prefer to optionally call SDL_SetKeymap and then use SDL_SendKeyboardKey. */
64extern bool SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, SDL_Keycode keycode, bool down);
65
66// Release all the autorelease keys
67extern void SDL_ReleaseAutoReleaseKeys(void);
68
69// Return true if any hardware key is pressed
70extern bool SDL_HardwareKeyboardKeyPressed(void);
71
72// Send keyboard text input
73extern void SDL_SendKeyboardText(const char *text);
74
75// Send editing text for selected range from start to end
76extern void SDL_SendEditingText(const char *text, int start, int length);
77
78// Send editing text candidates, which will be copied into the event
79extern void SDL_SendEditingTextCandidates(char **candidates, int num_candidates, int selected_candidate, bool horizontal);
80
81// Shutdown the keyboard subsystem
82extern void SDL_QuitKeyboard(void);
83
84// Toggle on or off pieces of the keyboard mod state.
85extern void SDL_ToggleModState(SDL_Keymod modstate, bool toggle);
86
87#endif // SDL_keyboard_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_keymap.c b/contrib/SDL-3.2.8/src/events/SDL_keymap.c
new file mode 100644
index 0000000..bd08786
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_keymap.c
@@ -0,0 +1,1153 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#include "SDL_keymap_c.h"
24#include "SDL_keyboard_c.h"
25
26struct SDL_Keymap
27{
28 SDL_HashTable *scancode_to_keycode;
29 SDL_HashTable *keycode_to_scancode;
30};
31
32static SDL_Keycode SDL_GetDefaultKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate);
33static SDL_Scancode SDL_GetDefaultScancodeFromKey(SDL_Keycode key, SDL_Keymod *modstate);
34
35SDL_Keymap *SDL_CreateKeymap(void)
36{
37 SDL_Keymap *keymap = (SDL_Keymap *)SDL_malloc(sizeof(*keymap));
38 if (!keymap) {
39 return NULL;
40 }
41
42 keymap->scancode_to_keycode = SDL_CreateHashTable(256, false, SDL_HashID, SDL_KeyMatchID, NULL, NULL);
43 keymap->keycode_to_scancode = SDL_CreateHashTable(256, false, SDL_HashID, SDL_KeyMatchID, NULL, NULL);
44 if (!keymap->scancode_to_keycode || !keymap->keycode_to_scancode) {
45 SDL_DestroyKeymap(keymap);
46 return NULL;
47 }
48 return keymap;
49}
50
51static SDL_Keymod NormalizeModifierStateForKeymap(SDL_Keymod modstate)
52{
53 // The modifiers that affect the keymap are: SHIFT, CAPS, ALT, MODE, and LEVEL5
54 modstate &= (SDL_KMOD_SHIFT | SDL_KMOD_CAPS | SDL_KMOD_ALT | SDL_KMOD_MODE | SDL_KMOD_LEVEL5);
55
56 // If either right or left Shift are set, set both in the output
57 if (modstate & SDL_KMOD_SHIFT) {
58 modstate |= SDL_KMOD_SHIFT;
59 }
60
61 // If either right or left Alt are set, set both in the output
62 if (modstate & SDL_KMOD_ALT) {
63 modstate |= SDL_KMOD_ALT;
64 }
65
66 return modstate;
67}
68
69void SDL_SetKeymapEntry(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate, SDL_Keycode keycode)
70{
71 if (!keymap) {
72 return;
73 }
74
75 modstate = NormalizeModifierStateForKeymap(modstate);
76 Uint32 key = ((Uint32)modstate << 16) | scancode;
77 const void *value;
78 if (SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) {
79 const SDL_Keycode existing_keycode = (SDL_Keycode)(uintptr_t)value;
80 if (existing_keycode == keycode) {
81 // We already have this mapping
82 return;
83 }
84 // InsertIntoHashTable will replace the existing entry in the keymap atomically.
85 }
86 SDL_InsertIntoHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, (void *)(uintptr_t)keycode, true);
87
88 bool update_keycode = true;
89 if (SDL_FindInHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, &value)) {
90 const Uint32 existing_value = (Uint32)(uintptr_t)value;
91 const SDL_Keymod existing_modstate = (SDL_Keymod)(existing_value >> 16);
92
93 // Keep the simplest combination of scancode and modifiers to generate this keycode
94 if (existing_modstate <= modstate) {
95 update_keycode = false;
96 }
97 }
98 if (update_keycode) {
99 SDL_InsertIntoHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, (void *)(uintptr_t)key, true);
100 }
101}
102
103SDL_Keycode SDL_GetKeymapKeycode(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate)
104{
105 SDL_Keycode keycode;
106
107 const Uint32 key = ((Uint32)NormalizeModifierStateForKeymap(modstate) << 16) | scancode;
108 const void *value;
109 if (keymap && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) {
110 keycode = (SDL_Keycode)(uintptr_t)value;
111 } else {
112 keycode = SDL_GetDefaultKeyFromScancode(scancode, modstate);
113 }
114 return keycode;
115}
116
117SDL_Scancode SDL_GetKeymapScancode(SDL_Keymap *keymap, SDL_Keycode keycode, SDL_Keymod *modstate)
118{
119 SDL_Scancode scancode;
120
121 const void *value;
122 if (keymap && SDL_FindInHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, &value)) {
123 scancode = (SDL_Scancode)((uintptr_t)value & 0xFFFF);
124 if (modstate) {
125 *modstate = (SDL_Keymod)((uintptr_t)value >> 16);
126 }
127 } else {
128 scancode = SDL_GetDefaultScancodeFromKey(keycode, modstate);
129 }
130 return scancode;
131}
132
133void SDL_DestroyKeymap(SDL_Keymap *keymap)
134{
135 if (!keymap) {
136 return;
137 }
138
139 SDL_DestroyHashTable(keymap->scancode_to_keycode);
140 SDL_DestroyHashTable(keymap->keycode_to_scancode);
141 SDL_free(keymap);
142}
143
144static const SDL_Keycode normal_default_symbols[] = {
145 SDLK_1,
146 SDLK_2,
147 SDLK_3,
148 SDLK_4,
149 SDLK_5,
150 SDLK_6,
151 SDLK_7,
152 SDLK_8,
153 SDLK_9,
154 SDLK_0,
155 SDLK_RETURN,
156 SDLK_ESCAPE,
157 SDLK_BACKSPACE,
158 SDLK_TAB,
159 SDLK_SPACE,
160 SDLK_MINUS,
161 SDLK_EQUALS,
162 SDLK_LEFTBRACKET,
163 SDLK_RIGHTBRACKET,
164 SDLK_BACKSLASH,
165 SDLK_HASH,
166 SDLK_SEMICOLON,
167 SDLK_APOSTROPHE,
168 SDLK_GRAVE,
169 SDLK_COMMA,
170 SDLK_PERIOD,
171 SDLK_SLASH,
172};
173
174static const SDL_Keycode shifted_default_symbols[] = {
175 SDLK_EXCLAIM,
176 SDLK_AT,
177 SDLK_HASH,
178 SDLK_DOLLAR,
179 SDLK_PERCENT,
180 SDLK_CARET,
181 SDLK_AMPERSAND,
182 SDLK_ASTERISK,
183 SDLK_LEFTPAREN,
184 SDLK_RIGHTPAREN,
185 SDLK_RETURN,
186 SDLK_ESCAPE,
187 SDLK_BACKSPACE,
188 SDLK_TAB,
189 SDLK_SPACE,
190 SDLK_UNDERSCORE,
191 SDLK_PLUS,
192 SDLK_LEFTBRACE,
193 SDLK_RIGHTBRACE,
194 SDLK_PIPE,
195 SDLK_HASH,
196 SDLK_COLON,
197 SDLK_DBLAPOSTROPHE,
198 SDLK_TILDE,
199 SDLK_LESS,
200 SDLK_GREATER,
201 SDLK_QUESTION
202};
203
204static const struct
205{
206 SDL_Keycode keycode;
207 SDL_Scancode scancode;
208} extended_default_symbols[] = {
209 { SDLK_LEFT_TAB, SDL_SCANCODE_TAB },
210 { SDLK_MULTI_KEY_COMPOSE, SDL_SCANCODE_APPLICATION }, // Sun keyboards
211 { SDLK_LMETA, SDL_SCANCODE_LGUI },
212 { SDLK_RMETA, SDL_SCANCODE_RGUI },
213 { SDLK_RHYPER, SDL_SCANCODE_APPLICATION }
214};
215
216static SDL_Keycode SDL_GetDefaultKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate)
217{
218 if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_SCANCODE_COUNT) {
219 SDL_InvalidParamError("scancode");
220 return SDLK_UNKNOWN;
221 }
222
223 if (scancode < SDL_SCANCODE_A) {
224 return SDLK_UNKNOWN;
225 }
226
227 if (scancode < SDL_SCANCODE_1) {
228 bool shifted = (modstate & SDL_KMOD_SHIFT) ? true : false;
229#ifdef SDL_PLATFORM_APPLE
230 // Apple maps to upper case for either shift or capslock inclusive
231 if (modstate & SDL_KMOD_CAPS) {
232 shifted = true;
233 }
234#else
235 if (modstate & SDL_KMOD_CAPS) {
236 shifted = !shifted;
237 }
238#endif
239 if (modstate & SDL_KMOD_MODE) {
240 return SDLK_UNKNOWN;
241 }
242 if (!shifted) {
243 return (SDL_Keycode)('a' + scancode - SDL_SCANCODE_A);
244 } else {
245 return (SDL_Keycode)('A' + scancode - SDL_SCANCODE_A);
246 }
247 }
248
249 if (scancode < SDL_SCANCODE_CAPSLOCK) {
250 bool shifted = (modstate & SDL_KMOD_SHIFT) ? true : false;
251
252 if (modstate & SDL_KMOD_MODE) {
253 return SDLK_UNKNOWN;
254 }
255 if (!shifted) {
256 return normal_default_symbols[scancode - SDL_SCANCODE_1];
257 } else {
258 return shifted_default_symbols[scancode - SDL_SCANCODE_1];
259 }
260 }
261
262 // These scancodes are not mapped to printable keycodes
263 switch (scancode) {
264 case SDL_SCANCODE_DELETE:
265 return SDLK_DELETE;
266 case SDL_SCANCODE_CAPSLOCK:
267 return SDLK_CAPSLOCK;
268 case SDL_SCANCODE_F1:
269 return SDLK_F1;
270 case SDL_SCANCODE_F2:
271 return SDLK_F2;
272 case SDL_SCANCODE_F3:
273 return SDLK_F3;
274 case SDL_SCANCODE_F4:
275 return SDLK_F4;
276 case SDL_SCANCODE_F5:
277 return SDLK_F5;
278 case SDL_SCANCODE_F6:
279 return SDLK_F6;
280 case SDL_SCANCODE_F7:
281 return SDLK_F7;
282 case SDL_SCANCODE_F8:
283 return SDLK_F8;
284 case SDL_SCANCODE_F9:
285 return SDLK_F9;
286 case SDL_SCANCODE_F10:
287 return SDLK_F10;
288 case SDL_SCANCODE_F11:
289 return SDLK_F11;
290 case SDL_SCANCODE_F12:
291 return SDLK_F12;
292 case SDL_SCANCODE_PRINTSCREEN:
293 return SDLK_PRINTSCREEN;
294 case SDL_SCANCODE_SCROLLLOCK:
295 return SDLK_SCROLLLOCK;
296 case SDL_SCANCODE_PAUSE:
297 return SDLK_PAUSE;
298 case SDL_SCANCODE_INSERT:
299 return SDLK_INSERT;
300 case SDL_SCANCODE_HOME:
301 return SDLK_HOME;
302 case SDL_SCANCODE_PAGEUP:
303 return SDLK_PAGEUP;
304 case SDL_SCANCODE_END:
305 return SDLK_END;
306 case SDL_SCANCODE_PAGEDOWN:
307 return SDLK_PAGEDOWN;
308 case SDL_SCANCODE_RIGHT:
309 return SDLK_RIGHT;
310 case SDL_SCANCODE_LEFT:
311 return SDLK_LEFT;
312 case SDL_SCANCODE_DOWN:
313 return SDLK_DOWN;
314 case SDL_SCANCODE_UP:
315 return SDLK_UP;
316 case SDL_SCANCODE_NUMLOCKCLEAR:
317 return SDLK_NUMLOCKCLEAR;
318 case SDL_SCANCODE_KP_DIVIDE:
319 return SDLK_KP_DIVIDE;
320 case SDL_SCANCODE_KP_MULTIPLY:
321 return SDLK_KP_MULTIPLY;
322 case SDL_SCANCODE_KP_MINUS:
323 return SDLK_KP_MINUS;
324 case SDL_SCANCODE_KP_PLUS:
325 return SDLK_KP_PLUS;
326 case SDL_SCANCODE_KP_ENTER:
327 return SDLK_KP_ENTER;
328 case SDL_SCANCODE_KP_1:
329 return SDLK_KP_1;
330 case SDL_SCANCODE_KP_2:
331 return SDLK_KP_2;
332 case SDL_SCANCODE_KP_3:
333 return SDLK_KP_3;
334 case SDL_SCANCODE_KP_4:
335 return SDLK_KP_4;
336 case SDL_SCANCODE_KP_5:
337 return SDLK_KP_5;
338 case SDL_SCANCODE_KP_6:
339 return SDLK_KP_6;
340 case SDL_SCANCODE_KP_7:
341 return SDLK_KP_7;
342 case SDL_SCANCODE_KP_8:
343 return SDLK_KP_8;
344 case SDL_SCANCODE_KP_9:
345 return SDLK_KP_9;
346 case SDL_SCANCODE_KP_0:
347 return SDLK_KP_0;
348 case SDL_SCANCODE_KP_PERIOD:
349 return SDLK_KP_PERIOD;
350 case SDL_SCANCODE_APPLICATION:
351 return SDLK_APPLICATION;
352 case SDL_SCANCODE_POWER:
353 return SDLK_POWER;
354 case SDL_SCANCODE_KP_EQUALS:
355 return SDLK_KP_EQUALS;
356 case SDL_SCANCODE_F13:
357 return SDLK_F13;
358 case SDL_SCANCODE_F14:
359 return SDLK_F14;
360 case SDL_SCANCODE_F15:
361 return SDLK_F15;
362 case SDL_SCANCODE_F16:
363 return SDLK_F16;
364 case SDL_SCANCODE_F17:
365 return SDLK_F17;
366 case SDL_SCANCODE_F18:
367 return SDLK_F18;
368 case SDL_SCANCODE_F19:
369 return SDLK_F19;
370 case SDL_SCANCODE_F20:
371 return SDLK_F20;
372 case SDL_SCANCODE_F21:
373 return SDLK_F21;
374 case SDL_SCANCODE_F22:
375 return SDLK_F22;
376 case SDL_SCANCODE_F23:
377 return SDLK_F23;
378 case SDL_SCANCODE_F24:
379 return SDLK_F24;
380 case SDL_SCANCODE_EXECUTE:
381 return SDLK_EXECUTE;
382 case SDL_SCANCODE_HELP:
383 return SDLK_HELP;
384 case SDL_SCANCODE_MENU:
385 return SDLK_MENU;
386 case SDL_SCANCODE_SELECT:
387 return SDLK_SELECT;
388 case SDL_SCANCODE_STOP:
389 return SDLK_STOP;
390 case SDL_SCANCODE_AGAIN:
391 return SDLK_AGAIN;
392 case SDL_SCANCODE_UNDO:
393 return SDLK_UNDO;
394 case SDL_SCANCODE_CUT:
395 return SDLK_CUT;
396 case SDL_SCANCODE_COPY:
397 return SDLK_COPY;
398 case SDL_SCANCODE_PASTE:
399 return SDLK_PASTE;
400 case SDL_SCANCODE_FIND:
401 return SDLK_FIND;
402 case SDL_SCANCODE_MUTE:
403 return SDLK_MUTE;
404 case SDL_SCANCODE_VOLUMEUP:
405 return SDLK_VOLUMEUP;
406 case SDL_SCANCODE_VOLUMEDOWN:
407 return SDLK_VOLUMEDOWN;
408 case SDL_SCANCODE_KP_COMMA:
409 return SDLK_KP_COMMA;
410 case SDL_SCANCODE_KP_EQUALSAS400:
411 return SDLK_KP_EQUALSAS400;
412 case SDL_SCANCODE_ALTERASE:
413 return SDLK_ALTERASE;
414 case SDL_SCANCODE_SYSREQ:
415 return SDLK_SYSREQ;
416 case SDL_SCANCODE_CANCEL:
417 return SDLK_CANCEL;
418 case SDL_SCANCODE_CLEAR:
419 return SDLK_CLEAR;
420 case SDL_SCANCODE_PRIOR:
421 return SDLK_PRIOR;
422 case SDL_SCANCODE_RETURN2:
423 return SDLK_RETURN2;
424 case SDL_SCANCODE_SEPARATOR:
425 return SDLK_SEPARATOR;
426 case SDL_SCANCODE_OUT:
427 return SDLK_OUT;
428 case SDL_SCANCODE_OPER:
429 return SDLK_OPER;
430 case SDL_SCANCODE_CLEARAGAIN:
431 return SDLK_CLEARAGAIN;
432 case SDL_SCANCODE_CRSEL:
433 return SDLK_CRSEL;
434 case SDL_SCANCODE_EXSEL:
435 return SDLK_EXSEL;
436 case SDL_SCANCODE_KP_00:
437 return SDLK_KP_00;
438 case SDL_SCANCODE_KP_000:
439 return SDLK_KP_000;
440 case SDL_SCANCODE_THOUSANDSSEPARATOR:
441 return SDLK_THOUSANDSSEPARATOR;
442 case SDL_SCANCODE_DECIMALSEPARATOR:
443 return SDLK_DECIMALSEPARATOR;
444 case SDL_SCANCODE_CURRENCYUNIT:
445 return SDLK_CURRENCYUNIT;
446 case SDL_SCANCODE_CURRENCYSUBUNIT:
447 return SDLK_CURRENCYSUBUNIT;
448 case SDL_SCANCODE_KP_LEFTPAREN:
449 return SDLK_KP_LEFTPAREN;
450 case SDL_SCANCODE_KP_RIGHTPAREN:
451 return SDLK_KP_RIGHTPAREN;
452 case SDL_SCANCODE_KP_LEFTBRACE:
453 return SDLK_KP_LEFTBRACE;
454 case SDL_SCANCODE_KP_RIGHTBRACE:
455 return SDLK_KP_RIGHTBRACE;
456 case SDL_SCANCODE_KP_TAB:
457 return SDLK_KP_TAB;
458 case SDL_SCANCODE_KP_BACKSPACE:
459 return SDLK_KP_BACKSPACE;
460 case SDL_SCANCODE_KP_A:
461 return SDLK_KP_A;
462 case SDL_SCANCODE_KP_B:
463 return SDLK_KP_B;
464 case SDL_SCANCODE_KP_C:
465 return SDLK_KP_C;
466 case SDL_SCANCODE_KP_D:
467 return SDLK_KP_D;
468 case SDL_SCANCODE_KP_E:
469 return SDLK_KP_E;
470 case SDL_SCANCODE_KP_F:
471 return SDLK_KP_F;
472 case SDL_SCANCODE_KP_XOR:
473 return SDLK_KP_XOR;
474 case SDL_SCANCODE_KP_POWER:
475 return SDLK_KP_POWER;
476 case SDL_SCANCODE_KP_PERCENT:
477 return SDLK_KP_PERCENT;
478 case SDL_SCANCODE_KP_LESS:
479 return SDLK_KP_LESS;
480 case SDL_SCANCODE_KP_GREATER:
481 return SDLK_KP_GREATER;
482 case SDL_SCANCODE_KP_AMPERSAND:
483 return SDLK_KP_AMPERSAND;
484 case SDL_SCANCODE_KP_DBLAMPERSAND:
485 return SDLK_KP_DBLAMPERSAND;
486 case SDL_SCANCODE_KP_VERTICALBAR:
487 return SDLK_KP_VERTICALBAR;
488 case SDL_SCANCODE_KP_DBLVERTICALBAR:
489 return SDLK_KP_DBLVERTICALBAR;
490 case SDL_SCANCODE_KP_COLON:
491 return SDLK_KP_COLON;
492 case SDL_SCANCODE_KP_HASH:
493 return SDLK_KP_HASH;
494 case SDL_SCANCODE_KP_SPACE:
495 return SDLK_KP_SPACE;
496 case SDL_SCANCODE_KP_AT:
497 return SDLK_KP_AT;
498 case SDL_SCANCODE_KP_EXCLAM:
499 return SDLK_KP_EXCLAM;
500 case SDL_SCANCODE_KP_MEMSTORE:
501 return SDLK_KP_MEMSTORE;
502 case SDL_SCANCODE_KP_MEMRECALL:
503 return SDLK_KP_MEMRECALL;
504 case SDL_SCANCODE_KP_MEMCLEAR:
505 return SDLK_KP_MEMCLEAR;
506 case SDL_SCANCODE_KP_MEMADD:
507 return SDLK_KP_MEMADD;
508 case SDL_SCANCODE_KP_MEMSUBTRACT:
509 return SDLK_KP_MEMSUBTRACT;
510 case SDL_SCANCODE_KP_MEMMULTIPLY:
511 return SDLK_KP_MEMMULTIPLY;
512 case SDL_SCANCODE_KP_MEMDIVIDE:
513 return SDLK_KP_MEMDIVIDE;
514 case SDL_SCANCODE_KP_PLUSMINUS:
515 return SDLK_KP_PLUSMINUS;
516 case SDL_SCANCODE_KP_CLEAR:
517 return SDLK_KP_CLEAR;
518 case SDL_SCANCODE_KP_CLEARENTRY:
519 return SDLK_KP_CLEARENTRY;
520 case SDL_SCANCODE_KP_BINARY:
521 return SDLK_KP_BINARY;
522 case SDL_SCANCODE_KP_OCTAL:
523 return SDLK_KP_OCTAL;
524 case SDL_SCANCODE_KP_DECIMAL:
525 return SDLK_KP_DECIMAL;
526 case SDL_SCANCODE_KP_HEXADECIMAL:
527 return SDLK_KP_HEXADECIMAL;
528 case SDL_SCANCODE_LCTRL:
529 return SDLK_LCTRL;
530 case SDL_SCANCODE_LSHIFT:
531 return SDLK_LSHIFT;
532 case SDL_SCANCODE_LALT:
533 return SDLK_LALT;
534 case SDL_SCANCODE_LGUI:
535 return SDLK_LGUI;
536 case SDL_SCANCODE_RCTRL:
537 return SDLK_RCTRL;
538 case SDL_SCANCODE_RSHIFT:
539 return SDLK_RSHIFT;
540 case SDL_SCANCODE_RALT:
541 return SDLK_RALT;
542 case SDL_SCANCODE_RGUI:
543 return SDLK_RGUI;
544 case SDL_SCANCODE_MODE:
545 return SDLK_MODE;
546 case SDL_SCANCODE_SLEEP:
547 return SDLK_SLEEP;
548 case SDL_SCANCODE_WAKE:
549 return SDLK_WAKE;
550 case SDL_SCANCODE_CHANNEL_INCREMENT:
551 return SDLK_CHANNEL_INCREMENT;
552 case SDL_SCANCODE_CHANNEL_DECREMENT:
553 return SDLK_CHANNEL_DECREMENT;
554 case SDL_SCANCODE_MEDIA_PLAY:
555 return SDLK_MEDIA_PLAY;
556 case SDL_SCANCODE_MEDIA_PAUSE:
557 return SDLK_MEDIA_PAUSE;
558 case SDL_SCANCODE_MEDIA_RECORD:
559 return SDLK_MEDIA_RECORD;
560 case SDL_SCANCODE_MEDIA_FAST_FORWARD:
561 return SDLK_MEDIA_FAST_FORWARD;
562 case SDL_SCANCODE_MEDIA_REWIND:
563 return SDLK_MEDIA_REWIND;
564 case SDL_SCANCODE_MEDIA_NEXT_TRACK:
565 return SDLK_MEDIA_NEXT_TRACK;
566 case SDL_SCANCODE_MEDIA_PREVIOUS_TRACK:
567 return SDLK_MEDIA_PREVIOUS_TRACK;
568 case SDL_SCANCODE_MEDIA_STOP:
569 return SDLK_MEDIA_STOP;
570 case SDL_SCANCODE_MEDIA_EJECT:
571 return SDLK_MEDIA_EJECT;
572 case SDL_SCANCODE_MEDIA_PLAY_PAUSE:
573 return SDLK_MEDIA_PLAY_PAUSE;
574 case SDL_SCANCODE_MEDIA_SELECT:
575 return SDLK_MEDIA_SELECT;
576 case SDL_SCANCODE_AC_NEW:
577 return SDLK_AC_NEW;
578 case SDL_SCANCODE_AC_OPEN:
579 return SDLK_AC_OPEN;
580 case SDL_SCANCODE_AC_CLOSE:
581 return SDLK_AC_CLOSE;
582 case SDL_SCANCODE_AC_EXIT:
583 return SDLK_AC_EXIT;
584 case SDL_SCANCODE_AC_SAVE:
585 return SDLK_AC_SAVE;
586 case SDL_SCANCODE_AC_PRINT:
587 return SDLK_AC_PRINT;
588 case SDL_SCANCODE_AC_PROPERTIES:
589 return SDLK_AC_PROPERTIES;
590 case SDL_SCANCODE_AC_SEARCH:
591 return SDLK_AC_SEARCH;
592 case SDL_SCANCODE_AC_HOME:
593 return SDLK_AC_HOME;
594 case SDL_SCANCODE_AC_BACK:
595 return SDLK_AC_BACK;
596 case SDL_SCANCODE_AC_FORWARD:
597 return SDLK_AC_FORWARD;
598 case SDL_SCANCODE_AC_STOP:
599 return SDLK_AC_STOP;
600 case SDL_SCANCODE_AC_REFRESH:
601 return SDLK_AC_REFRESH;
602 case SDL_SCANCODE_AC_BOOKMARKS:
603 return SDLK_AC_BOOKMARKS;
604 case SDL_SCANCODE_SOFTLEFT:
605 return SDLK_SOFTLEFT;
606 case SDL_SCANCODE_SOFTRIGHT:
607 return SDLK_SOFTRIGHT;
608 case SDL_SCANCODE_CALL:
609 return SDLK_CALL;
610 case SDL_SCANCODE_ENDCALL:
611 return SDLK_ENDCALL;
612 default:
613 return SDLK_UNKNOWN;
614 }
615}
616
617static SDL_Scancode SDL_GetDefaultScancodeFromKey(SDL_Keycode key, SDL_Keymod *modstate)
618{
619 if (modstate) {
620 *modstate = SDL_KMOD_NONE;
621 }
622
623 if (key == SDLK_UNKNOWN) {
624 return SDL_SCANCODE_UNKNOWN;
625 }
626
627 if (key & SDLK_EXTENDED_MASK) {
628 for (int i = 0; i < SDL_arraysize(extended_default_symbols); ++i) {
629 if (extended_default_symbols[i].keycode == key) {
630 return extended_default_symbols[i].scancode;
631 }
632 }
633
634 return SDL_SCANCODE_UNKNOWN;
635 }
636
637 if (key & SDLK_SCANCODE_MASK) {
638 return (SDL_Scancode)(key & ~SDLK_SCANCODE_MASK);
639 }
640
641 if (key >= SDLK_A && key <= SDLK_Z) {
642 return (SDL_Scancode)(SDL_SCANCODE_A + key - SDLK_A);
643 }
644
645 if (key >= 'A' && key <= 'Z') {
646 if (modstate) {
647 *modstate = SDL_KMOD_SHIFT;
648 }
649 return (SDL_Scancode)(SDL_SCANCODE_A + key - 'A');
650 }
651
652 for (int i = 0; i < SDL_arraysize(normal_default_symbols); ++i) {
653 if (key == normal_default_symbols[i]) {
654 return(SDL_Scancode)(SDL_SCANCODE_1 + i);
655 }
656 }
657
658 for (int i = 0; i < SDL_arraysize(shifted_default_symbols); ++i) {
659 if (key == shifted_default_symbols[i]) {
660 if (modstate) {
661 *modstate = SDL_KMOD_SHIFT;
662 }
663 return(SDL_Scancode)(SDL_SCANCODE_1 + i);
664 }
665 }
666
667 if (key == SDLK_DELETE) {
668 return SDL_SCANCODE_DELETE;
669 }
670
671 return SDL_SCANCODE_UNKNOWN;
672}
673
674static const char *SDL_scancode_names[SDL_SCANCODE_COUNT] =
675{
676 /* 0 */ NULL,
677 /* 1 */ NULL,
678 /* 2 */ NULL,
679 /* 3 */ NULL,
680 /* 4 */ "A",
681 /* 5 */ "B",
682 /* 6 */ "C",
683 /* 7 */ "D",
684 /* 8 */ "E",
685 /* 9 */ "F",
686 /* 10 */ "G",
687 /* 11 */ "H",
688 /* 12 */ "I",
689 /* 13 */ "J",
690 /* 14 */ "K",
691 /* 15 */ "L",
692 /* 16 */ "M",
693 /* 17 */ "N",
694 /* 18 */ "O",
695 /* 19 */ "P",
696 /* 20 */ "Q",
697 /* 21 */ "R",
698 /* 22 */ "S",
699 /* 23 */ "T",
700 /* 24 */ "U",
701 /* 25 */ "V",
702 /* 26 */ "W",
703 /* 27 */ "X",
704 /* 28 */ "Y",
705 /* 29 */ "Z",
706 /* 30 */ "1",
707 /* 31 */ "2",
708 /* 32 */ "3",
709 /* 33 */ "4",
710 /* 34 */ "5",
711 /* 35 */ "6",
712 /* 36 */ "7",
713 /* 37 */ "8",
714 /* 38 */ "9",
715 /* 39 */ "0",
716 /* 40 */ "Return",
717 /* 41 */ "Escape",
718 /* 42 */ "Backspace",
719 /* 43 */ "Tab",
720 /* 44 */ "Space",
721 /* 45 */ "-",
722 /* 46 */ "=",
723 /* 47 */ "[",
724 /* 48 */ "]",
725 /* 49 */ "\\",
726 /* 50 */ "#",
727 /* 51 */ ";",
728 /* 52 */ "'",
729 /* 53 */ "`",
730 /* 54 */ ",",
731 /* 55 */ ".",
732 /* 56 */ "/",
733 /* 57 */ "CapsLock",
734 /* 58 */ "F1",
735 /* 59 */ "F2",
736 /* 60 */ "F3",
737 /* 61 */ "F4",
738 /* 62 */ "F5",
739 /* 63 */ "F6",
740 /* 64 */ "F7",
741 /* 65 */ "F8",
742 /* 66 */ "F9",
743 /* 67 */ "F10",
744 /* 68 */ "F11",
745 /* 69 */ "F12",
746 /* 70 */ "PrintScreen",
747 /* 71 */ "ScrollLock",
748 /* 72 */ "Pause",
749 /* 73 */ "Insert",
750 /* 74 */ "Home",
751 /* 75 */ "PageUp",
752 /* 76 */ "Delete",
753 /* 77 */ "End",
754 /* 78 */ "PageDown",
755 /* 79 */ "Right",
756 /* 80 */ "Left",
757 /* 81 */ "Down",
758 /* 82 */ "Up",
759 /* 83 */ "Numlock",
760 /* 84 */ "Keypad /",
761 /* 85 */ "Keypad *",
762 /* 86 */ "Keypad -",
763 /* 87 */ "Keypad +",
764 /* 88 */ "Keypad Enter",
765 /* 89 */ "Keypad 1",
766 /* 90 */ "Keypad 2",
767 /* 91 */ "Keypad 3",
768 /* 92 */ "Keypad 4",
769 /* 93 */ "Keypad 5",
770 /* 94 */ "Keypad 6",
771 /* 95 */ "Keypad 7",
772 /* 96 */ "Keypad 8",
773 /* 97 */ "Keypad 9",
774 /* 98 */ "Keypad 0",
775 /* 99 */ "Keypad .",
776 /* 100 */ "NonUSBackslash",
777 /* 101 */ "Application",
778 /* 102 */ "Power",
779 /* 103 */ "Keypad =",
780 /* 104 */ "F13",
781 /* 105 */ "F14",
782 /* 106 */ "F15",
783 /* 107 */ "F16",
784 /* 108 */ "F17",
785 /* 109 */ "F18",
786 /* 110 */ "F19",
787 /* 111 */ "F20",
788 /* 112 */ "F21",
789 /* 113 */ "F22",
790 /* 114 */ "F23",
791 /* 115 */ "F24",
792 /* 116 */ "Execute",
793 /* 117 */ "Help",
794 /* 118 */ "Menu",
795 /* 119 */ "Select",
796 /* 120 */ "Stop",
797 /* 121 */ "Again",
798 /* 122 */ "Undo",
799 /* 123 */ "Cut",
800 /* 124 */ "Copy",
801 /* 125 */ "Paste",
802 /* 126 */ "Find",
803 /* 127 */ "Mute",
804 /* 128 */ "VolumeUp",
805 /* 129 */ "VolumeDown",
806 /* 130 */ NULL,
807 /* 131 */ NULL,
808 /* 132 */ NULL,
809 /* 133 */ "Keypad ,",
810 /* 134 */ "Keypad = (AS400)",
811 /* 135 */ "International 1",
812 /* 136 */ "International 2",
813 /* 137 */ "International 3",
814 /* 138 */ "International 4",
815 /* 139 */ "International 5",
816 /* 140 */ "International 6",
817 /* 141 */ "International 7",
818 /* 142 */ "International 8",
819 /* 143 */ "International 9",
820 /* 144 */ "Language 1",
821 /* 145 */ "Language 2",
822 /* 146 */ "Language 3",
823 /* 147 */ "Language 4",
824 /* 148 */ "Language 5",
825 /* 149 */ "Language 6",
826 /* 150 */ "Language 7",
827 /* 151 */ "Language 8",
828 /* 152 */ "Language 9",
829 /* 153 */ "AltErase",
830 /* 154 */ "SysReq",
831 /* 155 */ "Cancel",
832 /* 156 */ "Clear",
833 /* 157 */ "Prior",
834 /* 158 */ "Return",
835 /* 159 */ "Separator",
836 /* 160 */ "Out",
837 /* 161 */ "Oper",
838 /* 162 */ "Clear / Again",
839 /* 163 */ "CrSel",
840 /* 164 */ "ExSel",
841 /* 165 */ NULL,
842 /* 166 */ NULL,
843 /* 167 */ NULL,
844 /* 168 */ NULL,
845 /* 169 */ NULL,
846 /* 170 */ NULL,
847 /* 171 */ NULL,
848 /* 172 */ NULL,
849 /* 173 */ NULL,
850 /* 174 */ NULL,
851 /* 175 */ NULL,
852 /* 176 */ "Keypad 00",
853 /* 177 */ "Keypad 000",
854 /* 178 */ "ThousandsSeparator",
855 /* 179 */ "DecimalSeparator",
856 /* 180 */ "CurrencyUnit",
857 /* 181 */ "CurrencySubUnit",
858 /* 182 */ "Keypad (",
859 /* 183 */ "Keypad )",
860 /* 184 */ "Keypad {",
861 /* 185 */ "Keypad }",
862 /* 186 */ "Keypad Tab",
863 /* 187 */ "Keypad Backspace",
864 /* 188 */ "Keypad A",
865 /* 189 */ "Keypad B",
866 /* 190 */ "Keypad C",
867 /* 191 */ "Keypad D",
868 /* 192 */ "Keypad E",
869 /* 193 */ "Keypad F",
870 /* 194 */ "Keypad XOR",
871 /* 195 */ "Keypad ^",
872 /* 196 */ "Keypad %",
873 /* 197 */ "Keypad <",
874 /* 198 */ "Keypad >",
875 /* 199 */ "Keypad &",
876 /* 200 */ "Keypad &&",
877 /* 201 */ "Keypad |",
878 /* 202 */ "Keypad ||",
879 /* 203 */ "Keypad :",
880 /* 204 */ "Keypad #",
881 /* 205 */ "Keypad Space",
882 /* 206 */ "Keypad @",
883 /* 207 */ "Keypad !",
884 /* 208 */ "Keypad MemStore",
885 /* 209 */ "Keypad MemRecall",
886 /* 210 */ "Keypad MemClear",
887 /* 211 */ "Keypad MemAdd",
888 /* 212 */ "Keypad MemSubtract",
889 /* 213 */ "Keypad MemMultiply",
890 /* 214 */ "Keypad MemDivide",
891 /* 215 */ "Keypad +/-",
892 /* 216 */ "Keypad Clear",
893 /* 217 */ "Keypad ClearEntry",
894 /* 218 */ "Keypad Binary",
895 /* 219 */ "Keypad Octal",
896 /* 220 */ "Keypad Decimal",
897 /* 221 */ "Keypad Hexadecimal",
898 /* 222 */ NULL,
899 /* 223 */ NULL,
900 /* 224 */ "Left Ctrl",
901 /* 225 */ "Left Shift",
902 /* 226 */ "Left Alt",
903 /* 227 */ "Left GUI",
904 /* 228 */ "Right Ctrl",
905 /* 229 */ "Right Shift",
906 /* 230 */ "Right Alt",
907 /* 231 */ "Right GUI",
908 /* 232 */ NULL,
909 /* 233 */ NULL,
910 /* 234 */ NULL,
911 /* 235 */ NULL,
912 /* 236 */ NULL,
913 /* 237 */ NULL,
914 /* 238 */ NULL,
915 /* 239 */ NULL,
916 /* 240 */ NULL,
917 /* 241 */ NULL,
918 /* 242 */ NULL,
919 /* 243 */ NULL,
920 /* 244 */ NULL,
921 /* 245 */ NULL,
922 /* 246 */ NULL,
923 /* 247 */ NULL,
924 /* 248 */ NULL,
925 /* 249 */ NULL,
926 /* 250 */ NULL,
927 /* 251 */ NULL,
928 /* 252 */ NULL,
929 /* 253 */ NULL,
930 /* 254 */ NULL,
931 /* 255 */ NULL,
932 /* 256 */ NULL,
933 /* 257 */ "ModeSwitch",
934 /* 258 */ "Sleep",
935 /* 259 */ "Wake",
936 /* 260 */ "ChannelUp",
937 /* 261 */ "ChannelDown",
938 /* 262 */ "MediaPlay",
939 /* 263 */ "MediaPause",
940 /* 264 */ "MediaRecord",
941 /* 265 */ "MediaFastForward",
942 /* 266 */ "MediaRewind",
943 /* 267 */ "MediaTrackNext",
944 /* 268 */ "MediaTrackPrevious",
945 /* 269 */ "MediaStop",
946 /* 270 */ "Eject",
947 /* 271 */ "MediaPlayPause",
948 /* 272 */ "MediaSelect",
949 /* 273 */ "AC New",
950 /* 274 */ "AC Open",
951 /* 275 */ "AC Close",
952 /* 276 */ "AC Exit",
953 /* 277 */ "AC Save",
954 /* 278 */ "AC Print",
955 /* 279 */ "AC Properties",
956 /* 280 */ "AC Search",
957 /* 281 */ "AC Home",
958 /* 282 */ "AC Back",
959 /* 283 */ "AC Forward",
960 /* 284 */ "AC Stop",
961 /* 285 */ "AC Refresh",
962 /* 286 */ "AC Bookmarks",
963 /* 287 */ "SoftLeft",
964 /* 288 */ "SoftRight",
965 /* 289 */ "Call",
966 /* 290 */ "EndCall",
967};
968
969static const char *SDL_extended_key_names[] = {
970 "LeftTab", /* 0x01 SDLK_LEFT_TAB */
971 "Level5Shift", /* 0x02 SDLK_LEVEL5_SHIFT */
972 "MultiKeyCompose", /* 0x03 SDLK_MULTI_KEY_COMPOSE */
973 "Left Meta", /* 0x04 SDLK_LMETA */
974 "Right Meta", /* 0x05 SDLK_RMETA */
975 "Left Hyper", /* 0x06 SDLK_LHYPER */
976 "Right Hyper" /* 0x07 SDLK_RHYPER */
977};
978
979bool SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
980{
981 if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_SCANCODE_COUNT) {
982 return SDL_InvalidParamError("scancode");
983 }
984
985 SDL_scancode_names[scancode] = name;
986 return true;
987}
988
989const char *SDL_GetScancodeName(SDL_Scancode scancode)
990{
991 const char *name;
992 if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_SCANCODE_COUNT) {
993 SDL_InvalidParamError("scancode");
994 return "";
995 }
996
997 name = SDL_scancode_names[scancode];
998 if (!name) {
999 name = "";
1000 }
1001 // This is pointing to static memory or application managed memory
1002 return name;
1003}
1004
1005SDL_Scancode SDL_GetScancodeFromName(const char *name)
1006{
1007 int i;
1008
1009 if (!name || !*name) {
1010 SDL_InvalidParamError("name");
1011 return SDL_SCANCODE_UNKNOWN;
1012 }
1013
1014 for (i = 0; i < SDL_arraysize(SDL_scancode_names); ++i) {
1015 if (!SDL_scancode_names[i]) {
1016 continue;
1017 }
1018 if (SDL_strcasecmp(name, SDL_scancode_names[i]) == 0) {
1019 return (SDL_Scancode)i;
1020 }
1021 }
1022
1023 SDL_InvalidParamError("name");
1024 return SDL_SCANCODE_UNKNOWN;
1025}
1026
1027const char *SDL_GetKeyName(SDL_Keycode key)
1028{
1029 const bool uppercase = true;
1030 char name[8];
1031 char *end;
1032
1033 if (key & SDLK_SCANCODE_MASK) {
1034 return SDL_GetScancodeName((SDL_Scancode)(key & ~SDLK_SCANCODE_MASK));
1035 }
1036
1037 if (key & SDLK_EXTENDED_MASK) {
1038 const SDL_Keycode idx = (key & ~SDLK_EXTENDED_MASK);
1039 if (idx > 0 && (idx - 1) < SDL_arraysize(SDL_extended_key_names)) {
1040 return SDL_extended_key_names[idx - 1];
1041 }
1042
1043 // Key out of name index bounds.
1044 SDL_InvalidParamError("key");
1045 return "";
1046 }
1047
1048 switch (key) {
1049 case SDLK_RETURN:
1050 return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
1051 case SDLK_ESCAPE:
1052 return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
1053 case SDLK_BACKSPACE:
1054 return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
1055 case SDLK_TAB:
1056 return SDL_GetScancodeName(SDL_SCANCODE_TAB);
1057 case SDLK_SPACE:
1058 return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
1059 case SDLK_DELETE:
1060 return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
1061 default:
1062 if (uppercase) {
1063 // SDL_Keycode is defined as the unshifted key on the keyboard,
1064 // but the key name is defined as the letter printed on that key,
1065 // which is usually the shifted capital letter.
1066 if (key > 0x7F || (key >= 'a' && key <= 'z')) {
1067 SDL_Keymap *keymap = SDL_GetCurrentKeymap();
1068 SDL_Keymod modstate;
1069 SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate);
1070 if (scancode != SDL_SCANCODE_UNKNOWN && !(modstate & SDL_KMOD_SHIFT)) {
1071 SDL_Keycode capital = SDL_GetKeymapKeycode(keymap, scancode, SDL_KMOD_SHIFT);
1072 if (capital > 0x7F || (capital >= 'A' && capital <= 'Z')) {
1073 key = capital;
1074 }
1075 }
1076 }
1077 }
1078
1079 end = SDL_UCS4ToUTF8(key, name);
1080 *end = '\0';
1081 return SDL_GetPersistentString(name);
1082 }
1083}
1084
1085SDL_Keycode SDL_GetKeyFromName(const char *name)
1086{
1087 const bool uppercase = true;
1088 SDL_Keycode key;
1089
1090 // Check input
1091 if (!name) {
1092 return SDLK_UNKNOWN;
1093 }
1094
1095 // If it's a single UTF-8 character, then that's the keycode itself
1096 key = *(const unsigned char *)name;
1097 if (key >= 0xF0) {
1098 if (SDL_strlen(name) == 4) {
1099 int i = 0;
1100 key = (Uint16)(name[i] & 0x07) << 18;
1101 key |= (Uint16)(name[++i] & 0x3F) << 12;
1102 key |= (Uint16)(name[++i] & 0x3F) << 6;
1103 key |= (Uint16)(name[++i] & 0x3F);
1104 } else {
1105 key = SDLK_UNKNOWN;
1106 }
1107 } else if (key >= 0xE0) {
1108 if (SDL_strlen(name) == 3) {
1109 int i = 0;
1110 key = (Uint16)(name[i] & 0x0F) << 12;
1111 key |= (Uint16)(name[++i] & 0x3F) << 6;
1112 key |= (Uint16)(name[++i] & 0x3F);
1113 } else {
1114 key = SDLK_UNKNOWN;
1115 }
1116 } else if (key >= 0xC0) {
1117 if (SDL_strlen(name) == 2) {
1118 int i = 0;
1119 key = (Uint16)(name[i] & 0x1F) << 6;
1120 key |= (Uint16)(name[++i] & 0x3F);
1121 } else {
1122 key = SDLK_UNKNOWN;
1123 }
1124 } else {
1125 if (SDL_strlen(name) != 1) {
1126 key = SDLK_UNKNOWN;
1127 }
1128 }
1129
1130 if (key != SDLK_UNKNOWN) {
1131 if (uppercase) {
1132 // SDL_Keycode is defined as the unshifted key on the keyboard,
1133 // but the key name is defined as the letter printed on that key,
1134 // which is usually the shifted capital letter.
1135 SDL_Keymap *keymap = SDL_GetCurrentKeymap();
1136 SDL_Keymod modstate;
1137 SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate);
1138 if (scancode != SDL_SCANCODE_UNKNOWN && (modstate & (SDL_KMOD_SHIFT | SDL_KMOD_CAPS))) {
1139 key = SDL_GetKeymapKeycode(keymap, scancode, SDL_KMOD_NONE);
1140 }
1141 }
1142 return key;
1143 }
1144
1145 // Check the extended key names
1146 for (SDL_Keycode i = 0; i < SDL_arraysize(SDL_extended_key_names); ++i) {
1147 if (SDL_strcasecmp(name, SDL_extended_key_names[i]) == 0) {
1148 return (i + 1) | SDLK_EXTENDED_MASK;
1149 }
1150 }
1151
1152 return SDL_GetKeyFromScancode(SDL_GetScancodeFromName(name), SDL_KMOD_NONE, false);
1153}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_keymap_c.h b/contrib/SDL-3.2.8/src/events/SDL_keymap_c.h
new file mode 100644
index 0000000..9c80397
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_keymap_c.h
@@ -0,0 +1,35 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_keymap_c_h_
24#define SDL_keymap_c_h_
25
26typedef struct SDL_Keymap SDL_Keymap;
27
28SDL_Keymap *SDL_GetCurrentKeymap(void);
29SDL_Keymap *SDL_CreateKeymap(void);
30void SDL_SetKeymapEntry(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate, SDL_Keycode keycode);
31SDL_Keycode SDL_GetKeymapKeycode(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate);
32SDL_Scancode SDL_GetKeymapScancode(SDL_Keymap *keymap, SDL_Keycode keycode, SDL_Keymod *modstate);
33void SDL_DestroyKeymap(SDL_Keymap *keymap);
34
35#endif // SDL_keymap_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_keysym_to_keycode.c b/contrib/SDL-3.2.8/src/events/SDL_keysym_to_keycode.c
new file mode 100644
index 0000000..7cbfcb6
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_keysym_to_keycode.c
@@ -0,0 +1,68 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#if defined(SDL_VIDEO_DRIVER_WAYLAND) || defined(SDL_VIDEO_DRIVER_X11)
24
25#include "SDL_keyboard_c.h"
26#include "SDL_keysym_to_scancode_c.h"
27#include "imKStoUCS.h"
28
29
30// Extended key code mappings
31static const struct
32{
33 Uint32 keysym;
34 SDL_Keycode keycode;
35} keysym_to_keycode_table[] = {
36 { 0xfe03, SDLK_MODE }, // XK_ISO_Level3_Shift
37 { 0xfe11, SDLK_LEVEL5_SHIFT }, // XK_ISO_Level5_Shift
38 { 0xfe20, SDLK_LEFT_TAB }, // XK_ISO_Left_Tab
39 { 0xff20, SDLK_MULTI_KEY_COMPOSE }, // XK_Multi_key
40 { 0xffe7, SDLK_LMETA }, // XK_Meta_L
41 { 0xffe8, SDLK_RMETA }, // XK_Meta_R
42 { 0xffed, SDLK_LHYPER }, // XK_Hyper_L
43 { 0xffee, SDLK_RHYPER }, // XK_Hyper_R
44};
45
46SDL_Keycode SDL_GetKeyCodeFromKeySym(Uint32 keysym, Uint32 keycode, SDL_Keymod modifiers)
47{
48 SDL_Keycode sdl_keycode = SDL_KeySymToUcs4(keysym);
49
50 if (!sdl_keycode) {
51 for (int i = 0; i < SDL_arraysize(keysym_to_keycode_table); ++i) {
52 if (keysym == keysym_to_keycode_table[i].keysym) {
53 return keysym_to_keycode_table[i].keycode;
54 }
55 }
56 }
57
58 if (!sdl_keycode) {
59 const SDL_Scancode scancode = SDL_GetScancodeFromKeySym(keysym, keycode);
60 if (scancode != SDL_SCANCODE_UNKNOWN) {
61 sdl_keycode = SDL_GetKeymapKeycode(NULL, scancode, modifiers);
62 }
63 }
64
65 return sdl_keycode;
66}
67
68#endif // SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_X11
diff --git a/contrib/SDL-3.2.8/src/events/SDL_keysym_to_keycode_c.h b/contrib/SDL-3.2.8/src/events/SDL_keysym_to_keycode_c.h
new file mode 100644
index 0000000..2321d20
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_keysym_to_keycode_c.h
@@ -0,0 +1,28 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#ifndef SDL_keysym_to_keycode_c_h_
23#define SDL_keysym_to_keycode_c_h_
24
25// Convert a keysym to an SDL key code
26extern SDL_Keycode SDL_GetKeyCodeFromKeySym(Uint32 keysym, Uint32 keycode, SDL_Keymod modifiers);
27
28#endif // SDL_keysym_to_scancode_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_keysym_to_scancode.c b/contrib/SDL-3.2.8/src/events/SDL_keysym_to_scancode.c
new file mode 100644
index 0000000..8d43ca3
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_keysym_to_scancode.c
@@ -0,0 +1,439 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#if defined(SDL_VIDEO_DRIVER_WAYLAND) || defined(SDL_VIDEO_DRIVER_X11)
24
25#include "SDL_keyboard_c.h"
26#include "SDL_scancode_tables_c.h"
27#include "SDL_keysym_to_scancode_c.h"
28
29/* *INDENT-OFF* */ // clang-format off
30static const struct {
31 Uint32 keysym;
32 SDL_Scancode scancode;
33} KeySymToSDLScancode[] = {
34 { 0xFF9C, SDL_SCANCODE_KP_1 }, // XK_KP_End
35 { 0xFF99, SDL_SCANCODE_KP_2 }, // XK_KP_Down
36 { 0xFF9B, SDL_SCANCODE_KP_3 }, // XK_KP_Next
37 { 0xFF96, SDL_SCANCODE_KP_4 }, // XK_KP_Left
38 { 0xFF9D, SDL_SCANCODE_KP_5 }, // XK_KP_Begin
39 { 0xFF98, SDL_SCANCODE_KP_6 }, // XK_KP_Right
40 { 0xFF95, SDL_SCANCODE_KP_7 }, // XK_KP_Home
41 { 0xFF97, SDL_SCANCODE_KP_8 }, // XK_KP_Up
42 { 0xFF9A, SDL_SCANCODE_KP_9 }, // XK_KP_Prior
43 { 0xFF9E, SDL_SCANCODE_KP_0 }, // XK_KP_Insert
44 { 0xFF9F, SDL_SCANCODE_KP_PERIOD }, // XK_KP_Delete
45 { 0xFF62, SDL_SCANCODE_EXECUTE }, // XK_Execute
46 { 0xFFEE, SDL_SCANCODE_APPLICATION }, // XK_Hyper_R
47 { 0xFE03, SDL_SCANCODE_RALT }, // XK_ISO_Level3_Shift
48 { 0xFE20, SDL_SCANCODE_TAB }, // XK_ISO_Left_Tab
49 { 0xFFEB, SDL_SCANCODE_LGUI }, // XK_Super_L
50 { 0xFFEC, SDL_SCANCODE_RGUI }, // XK_Super_R
51 { 0xFF7E, SDL_SCANCODE_MODE }, // XK_Mode_switch
52 { 0x1008FF65, SDL_SCANCODE_MENU }, // XF86MenuKB
53 { 0x1008FF81, SDL_SCANCODE_F13 }, // XF86Tools
54 { 0x1008FF45, SDL_SCANCODE_F14 }, // XF86Launch5
55 { 0x1008FF46, SDL_SCANCODE_F15 }, // XF86Launch6
56 { 0x1008FF47, SDL_SCANCODE_F16 }, // XF86Launch7
57 { 0x1008FF48, SDL_SCANCODE_F17 }, // XF86Launch8
58 { 0x1008FF49, SDL_SCANCODE_F18 }, // XF86Launch9
59};
60
61// This is a mapping from X keysym to Linux keycode
62static const Uint32 LinuxKeycodeKeysyms[] = {
63 /* 0, 0x000 */ 0x0, // NoSymbol
64 /* 1, 0x001 */ 0xFF1B, // Escape
65 /* 2, 0x002 */ 0x31, // 1
66 /* 3, 0x003 */ 0x32, // 2
67 /* 4, 0x004 */ 0x33, // 3
68 /* 5, 0x005 */ 0x34, // 4
69 /* 6, 0x006 */ 0x35, // 5
70 /* 7, 0x007 */ 0x36, // 6
71 /* 8, 0x008 */ 0x37, // 7
72 /* 9, 0x009 */ 0x38, // 8
73 /* 10, 0x00a */ 0x39, // 9
74 /* 11, 0x00b */ 0x30, // 0
75 /* 12, 0x00c */ 0x2D, // minus
76 /* 13, 0x00d */ 0x3D, // equal
77 /* 14, 0x00e */ 0xFF08, // BackSpace
78 /* 15, 0x00f */ 0xFF09, // Tab
79 /* 16, 0x010 */ 0x71, // q
80 /* 17, 0x011 */ 0x77, // w
81 /* 18, 0x012 */ 0x65, // e
82 /* 19, 0x013 */ 0x72, // r
83 /* 20, 0x014 */ 0x74, // t
84 /* 21, 0x015 */ 0x79, // y
85 /* 22, 0x016 */ 0x75, // u
86 /* 23, 0x017 */ 0x69, // i
87 /* 24, 0x018 */ 0x6F, // o
88 /* 25, 0x019 */ 0x70, // p
89 /* 26, 0x01a */ 0x5B, // bracketleft
90 /* 27, 0x01b */ 0x5D, // bracketright
91 /* 28, 0x01c */ 0xFF0D, // Return
92 /* 29, 0x01d */ 0xFFE3, // Control_L
93 /* 30, 0x01e */ 0x61, // a
94 /* 31, 0x01f */ 0x73, // s
95 /* 32, 0x020 */ 0x64, // d
96 /* 33, 0x021 */ 0x66, // f
97 /* 34, 0x022 */ 0x67, // g
98 /* 35, 0x023 */ 0x68, // h
99 /* 36, 0x024 */ 0x6A, // j
100 /* 37, 0x025 */ 0x6B, // k
101 /* 38, 0x026 */ 0x6C, // l
102 /* 39, 0x027 */ 0x3B, // semicolon
103 /* 40, 0x028 */ 0x27, // apostrophe
104 /* 41, 0x029 */ 0x60, // grave
105 /* 42, 0x02a */ 0xFFE1, // Shift_L
106 /* 43, 0x02b */ 0x5C, // backslash
107 /* 44, 0x02c */ 0x7A, // z
108 /* 45, 0x02d */ 0x78, // x
109 /* 46, 0x02e */ 0x63, // c
110 /* 47, 0x02f */ 0x76, // v
111 /* 48, 0x030 */ 0x62, // b
112 /* 49, 0x031 */ 0x6E, // n
113 /* 50, 0x032 */ 0x6D, // m
114 /* 51, 0x033 */ 0x2C, // comma
115 /* 52, 0x034 */ 0x2E, // period
116 /* 53, 0x035 */ 0x2F, // slash
117 /* 54, 0x036 */ 0xFFE2, // Shift_R
118 /* 55, 0x037 */ 0xFFAA, // KP_Multiply
119 /* 56, 0x038 */ 0xFFE9, // Alt_L
120 /* 57, 0x039 */ 0x20, // space
121 /* 58, 0x03a */ 0xFFE5, // Caps_Lock
122 /* 59, 0x03b */ 0xFFBE, // F1
123 /* 60, 0x03c */ 0xFFBF, // F2
124 /* 61, 0x03d */ 0xFFC0, // F3
125 /* 62, 0x03e */ 0xFFC1, // F4
126 /* 63, 0x03f */ 0xFFC2, // F5
127 /* 64, 0x040 */ 0xFFC3, // F6
128 /* 65, 0x041 */ 0xFFC4, // F7
129 /* 66, 0x042 */ 0xFFC5, // F8
130 /* 67, 0x043 */ 0xFFC6, // F9
131 /* 68, 0x044 */ 0xFFC7, // F10
132 /* 69, 0x045 */ 0xFF7F, // Num_Lock
133 /* 70, 0x046 */ 0xFF14, // Scroll_Lock
134 /* 71, 0x047 */ 0xFFB7, // KP_7
135 /* 72, 0x048 */ 0XFFB8, // KP_8
136 /* 73, 0x049 */ 0XFFB9, // KP_9
137 /* 74, 0x04a */ 0xFFAD, // KP_Subtract
138 /* 75, 0x04b */ 0xFFB4, // KP_4
139 /* 76, 0x04c */ 0xFFB5, // KP_5
140 /* 77, 0x04d */ 0xFFB6, // KP_6
141 /* 78, 0x04e */ 0xFFAB, // KP_Add
142 /* 79, 0x04f */ 0xFFB1, // KP_1
143 /* 80, 0x050 */ 0xFFB2, // KP_2
144 /* 81, 0x051 */ 0xFFB3, // KP_3
145 /* 82, 0x052 */ 0xFFB0, // KP_0
146 /* 83, 0x053 */ 0xFFAE, // KP_Decimal
147 /* 84, 0x054 */ 0x0, // NoSymbol
148 /* 85, 0x055 */ 0x0, // NoSymbol
149 /* 86, 0x056 */ 0x3C, // less
150 /* 87, 0x057 */ 0xFFC8, // F11
151 /* 88, 0x058 */ 0xFFC9, // F12
152 /* 89, 0x059 */ 0x0, // NoSymbol
153 /* 90, 0x05a */ 0xFF26, // Katakana
154 /* 91, 0x05b */ 0xFF25, // Hiragana
155 /* 92, 0x05c */ 0xFF23, // Henkan_Mode
156 /* 93, 0x05d */ 0xFF27, // Hiragana_Katakana
157 /* 94, 0x05e */ 0xFF22, // Muhenkan
158 /* 95, 0x05f */ 0x0, // NoSymbol
159 /* 96, 0x060 */ 0xFF8D, // KP_Enter
160 /* 97, 0x061 */ 0xFFE4, // Control_R
161 /* 98, 0x062 */ 0xFFAF, // KP_Divide
162 /* 99, 0x063 */ 0xFF15, // Sys_Req
163 /* 100, 0x064 */ 0xFFEA, // Alt_R
164 /* 101, 0x065 */ 0xFF0A, // Linefeed
165 /* 102, 0x066 */ 0xFF50, // Home
166 /* 103, 0x067 */ 0xFF52, // Up
167 /* 104, 0x068 */ 0xFF55, // Prior
168 /* 105, 0x069 */ 0xFF51, // Left
169 /* 106, 0x06a */ 0xFF53, // Right
170 /* 107, 0x06b */ 0xFF57, // End
171 /* 108, 0x06c */ 0xFF54, // Down
172 /* 109, 0x06d */ 0xFF56, // Next
173 /* 110, 0x06e */ 0xFF63, // Insert
174 /* 111, 0x06f */ 0xFFFF, // Delete
175 /* 112, 0x070 */ 0x0, // NoSymbol
176 /* 113, 0x071 */ 0x1008FF12, // XF86AudioMute
177 /* 114, 0x072 */ 0x1008FF11, // XF86AudioLowerVolume
178 /* 115, 0x073 */ 0x1008FF13, // XF86AudioRaiseVolume
179 /* 116, 0x074 */ 0x1008FF2A, // XF86PowerOff
180 /* 117, 0x075 */ 0xFFBD, // KP_Equal
181 /* 118, 0x076 */ 0xB1, // plusminus
182 /* 119, 0x077 */ 0xFF13, // Pause
183 /* 120, 0x078 */ 0x1008FF4A, // XF86LaunchA
184 /* 121, 0x079 */ 0xFFAC, // KP_Separator
185 /* 122, 0x07a */ 0xFF31, // Hangul
186 /* 123, 0x07b */ 0xFF34, // Hangul_Hanja
187 /* 124, 0x07c */ 0x0, // NoSymbol
188 /* 125, 0x07d */ 0xFFE7, // Meta_L
189 /* 126, 0x07e */ 0xFFE8, // Meta_R
190 /* 127, 0x07f */ 0xFF67, // Menu
191 /* 128, 0x080 */ 0x00, // NoSymbol
192 /* 129, 0x081 */ 0xFF66, // Redo
193 /* 130, 0x082 */ 0x1005FF70, // SunProps
194 /* 131, 0x083 */ 0xFF65, // Undo
195 /* 132, 0x084 */ 0x1005FF71, // SunFront
196 /* 133, 0x085 */ 0x1008FF57, // XF86Copy
197 /* 134, 0x086 */ 0x1008FF6B, // XF86Open
198 /* 135, 0x087 */ 0x1008FF6D, // XF86Paste
199 /* 136, 0x088 */ 0xFF68, // Find
200 /* 137, 0x089 */ 0x1008FF58, // XF86Cut
201 /* 138, 0x08a */ 0xFF6A, // Help
202 /* 139, 0x08b */ 0xFF67, // Menu
203 /* 140, 0x08c */ 0x1008FF1D, // XF86Calculator
204 /* 141, 0x08d */ 0x0, // NoSymbol
205 /* 142, 0x08e */ 0x1008FF2F, // XF86Sleep
206 /* 143, 0x08f */ 0x1008FF2B, // XF86WakeUp
207 /* 144, 0x090 */ 0x1008FF5D, // XF86Explorer
208 /* 145, 0x091 */ 0x1008FF7B, // XF86Send
209 /* 146, 0x092 */ 0x0, // NoSymbol
210 /* 147, 0x093 */ 0x1008FF8A, // XF86Xfer
211 /* 148, 0x094 */ 0x1008FF41, // XF86Launch1
212 /* 149, 0x095 */ 0x1008FF42, // XF86Launch2
213 /* 150, 0x096 */ 0x1008FF2E, // XF86WWW
214 /* 151, 0x097 */ 0x1008FF5A, // XF86DOS
215 /* 152, 0x098 */ 0x1008FF2D, // XF86ScreenSaver
216 /* 153, 0x099 */ 0x1008FF74, // XF86RotateWindows
217 /* 154, 0x09a */ 0x1008FF7F, // XF86TaskPane
218 /* 155, 0x09b */ 0x1008FF19, // XF86Mail
219 /* 156, 0x09c */ 0x1008FF30, // XF86Favorites
220 /* 157, 0x09d */ 0x1008FF33, // XF86MyComputer
221 /* 158, 0x09e */ 0x1008FF26, // XF86Back
222 /* 159, 0x09f */ 0x1008FF27, // XF86Forward
223 /* 160, 0x0a0 */ 0x0, // NoSymbol
224 /* 161, 0x0a1 */ 0x1008FF2C, // XF86Eject
225 /* 162, 0x0a2 */ 0x1008FF2C, // XF86Eject
226 /* 163, 0x0a3 */ 0x1008FF17, // XF86AudioNext
227 /* 164, 0x0a4 */ 0x1008FF14, // XF86AudioPlay
228 /* 165, 0x0a5 */ 0x1008FF16, // XF86AudioPrev
229 /* 166, 0x0a6 */ 0x1008FF15, // XF86AudioStop
230 /* 167, 0x0a7 */ 0x1008FF1C, // XF86AudioRecord
231 /* 168, 0x0a8 */ 0x1008FF3E, // XF86AudioRewind
232 /* 169, 0x0a9 */ 0x1008FF6E, // XF86Phone
233 /* 170, 0x0aa */ 0x0, // NoSymbol
234 /* 171, 0x0ab */ 0x1008FF81, // XF86Tools
235 /* 172, 0x0ac */ 0x1008FF18, // XF86HomePage
236 /* 173, 0x0ad */ 0x1008FF73, // XF86Reload
237 /* 174, 0x0ae */ 0x1008FF56, // XF86Close
238 /* 175, 0x0af */ 0x0, // NoSymbol
239 /* 176, 0x0b0 */ 0x0, // NoSymbol
240 /* 177, 0x0b1 */ 0x1008FF78, // XF86ScrollUp
241 /* 178, 0x0b2 */ 0x1008FF79, // XF86ScrollDown
242 /* 179, 0x0b3 */ 0x0, // NoSymbol
243 /* 180, 0x0b4 */ 0x0, // NoSymbol
244 /* 181, 0x0b5 */ 0x1008FF68, // XF86New
245 /* 182, 0x0b6 */ 0xFF66, // Redo
246 /* 183, 0x0b7 */ 0xFFCA, // F13
247 /* 184, 0x0b8 */ 0xFFCB, // F14
248 /* 185, 0x0b9 */ 0xFFCC, // F15
249 /* 186, 0x0ba */ 0xFFCD, // F16
250 /* 187, 0x0bb */ 0xFFCE, // F17
251 /* 188, 0x0bc */ 0xFFCF, // F18
252 /* 189, 0x0bd */ 0xFFD0, // F19
253 /* 190, 0x0be */ 0xFFD1, // F20
254 /* 191, 0x0bf */ 0xFFD2, // F21
255 /* 192, 0x0c0 */ 0xFFD3, // F22
256 /* 193, 0x0c1 */ 0xFFD4, // F23
257 /* 194, 0x0c2 */ 0xFFD5, // F24
258 /* 195, 0x0c3 */ 0x0, // NoSymbol
259 /* 196, 0x0c4 */ 0x0, // NoSymbol
260 /* 197, 0x0c5 */ 0x0, // NoSymbol
261 /* 198, 0x0c6 */ 0x0, // NoSymbol
262 /* 199, 0x0c7 */ 0x0, // NoSymbol
263 /* 200, 0x0c8 */ 0x1008FF14, // XF86AudioPlay
264 /* 201, 0x0c9 */ 0x1008FF31, // XF86AudioPause
265 /* 202, 0x0ca */ 0x1008FF43, // XF86Launch3
266 /* 203, 0x0cb */ 0x1008FF44, // XF86Launch4
267 /* 204, 0x0cc */ 0x1008FF4B, // XF86LaunchB
268 /* 205, 0x0cd */ 0x1008FFA7, // XF86Suspend
269 /* 206, 0x0ce */ 0x1008FF56, // XF86Close
270 /* 207, 0x0cf */ 0x1008FF14, // XF86AudioPlay
271 /* 208, 0x0d0 */ 0x1008FF97, // XF86AudioForward
272 /* 209, 0x0d1 */ 0x0, // NoSymbol
273 /* 210, 0x0d2 */ 0xFF61, // Print
274 /* 211, 0x0d3 */ 0x0, // NoSymbol
275 /* 212, 0x0d4 */ 0x1008FF8F, // XF86WebCam
276 /* 213, 0x0d5 */ 0x1008FFB6, // XF86AudioPreset
277 /* 214, 0x0d6 */ 0x0, // NoSymbol
278 /* 215, 0x0d7 */ 0x1008FF19, // XF86Mail
279 /* 216, 0x0d8 */ 0x1008FF8E, // XF86Messenger
280 /* 217, 0x0d9 */ 0x1008FF1B, // XF86Search
281 /* 218, 0x0da */ 0x1008FF5F, // XF86Go
282 /* 219, 0x0db */ 0x1008FF3C, // XF86Finance
283 /* 220, 0x0dc */ 0x1008FF5E, // XF86Game
284 /* 221, 0x0dd */ 0x1008FF36, // XF86Shop
285 /* 222, 0x0de */ 0x0, // NoSymbol
286 /* 223, 0x0df */ 0xFF69, // Cancel
287 /* 224, 0x0e0 */ 0x1008FF03, // XF86MonBrightnessDown
288 /* 225, 0x0e1 */ 0x1008FF02, // XF86MonBrightnessUp
289 /* 226, 0x0e2 */ 0x1008FF32, // XF86AudioMedia
290 /* 227, 0x0e3 */ 0x1008FF59, // XF86Display
291 /* 228, 0x0e4 */ 0x1008FF04, // XF86KbdLightOnOff
292 /* 229, 0x0e5 */ 0x1008FF06, // XF86KbdBrightnessDown
293 /* 230, 0x0e6 */ 0x1008FF05, // XF86KbdBrightnessUp
294 /* 231, 0x0e7 */ 0x1008FF7B, // XF86Send
295 /* 232, 0x0e8 */ 0x1008FF72, // XF86Reply
296 /* 233, 0x0e9 */ 0x1008FF90, // XF86MailForward
297 /* 234, 0x0ea */ 0x1008FF77, // XF86Save
298 /* 235, 0x0eb */ 0x1008FF5B, // XF86Documents
299 /* 236, 0x0ec */ 0x1008FF93, // XF86Battery
300 /* 237, 0x0ed */ 0x1008FF94, // XF86Bluetooth
301 /* 238, 0x0ee */ 0x1008FF95, // XF86WLAN
302 /* 239, 0x0ef */ 0x1008FF96, // XF86UWB
303 /* 240, 0x0f0 */ 0x0, // NoSymbol
304 /* 241, 0x0f1 */ 0x1008FE22, // XF86Next_VMode
305 /* 242, 0x0f2 */ 0x1008FE23, // XF86Prev_VMode
306 /* 243, 0x0f3 */ 0x1008FF07, // XF86MonBrightnessCycle
307 /* 244, 0x0f4 */ 0x100810F4, // XF86BrightnessAuto
308 /* 245, 0x0f5 */ 0x100810F5, // XF86DisplayOff
309 /* 246, 0x0f6 */ 0x1008FFB4, // XF86WWAN
310 /* 247, 0x0f7 */ 0x1008FFB5, // XF86RFKill
311};
312
313#if 0 // Here is a script to generate the ExtendedLinuxKeycodeKeysyms table
314#!/bin/bash
315
316function process_line
317{
318 sym=$(echo "$1" | awk '{print $3}')
319 code=$(echo "$1" | sed 's,.*_EVDEVK(\(0x[0-9A-Fa-f]*\)).*,\1,')
320 value=$(grep -E "#define ${sym}\s" -R /usr/include/X11 | awk '{print $3}')
321 printf " { 0x%.8X, 0x%.3x }, /* $sym */\n" $value $code
322}
323
324grep -F "/* Use: " /usr/include/xkbcommon/xkbcommon-keysyms.h | grep -F _EVDEVK | while read line; do
325 process_line "$line"
326done
327#endif
328
329static const struct {
330 Uint32 keysym;
331 int linux_keycode;
332} ExtendedLinuxKeycodeKeysyms[] = {
333 { 0x1008FF2C, 0x0a2 }, // XF86XK_Eject
334 { 0x1008FF68, 0x0b5 }, // XF86XK_New
335 { 0x0000FF66, 0x0b6 }, // XK_Redo
336 { 0x1008FF4B, 0x0cc }, // XF86XK_LaunchB
337 { 0x1008FF59, 0x0e3 }, // XF86XK_Display
338 { 0x1008FF04, 0x0e4 }, // XF86XK_KbdLightOnOff
339 { 0x1008FF06, 0x0e5 }, // XF86XK_KbdBrightnessDown
340 { 0x1008FF05, 0x0e6 }, // XF86XK_KbdBrightnessUp
341 { 0x1008FF7B, 0x0e7 }, // XF86XK_Send
342 { 0x1008FF72, 0x0e8 }, // XF86XK_Reply
343 { 0x1008FF90, 0x0e9 }, // XF86XK_MailForward
344 { 0x1008FF77, 0x0ea }, // XF86XK_Save
345 { 0x1008FF5B, 0x0eb }, // XF86XK_Documents
346 { 0x1008FF93, 0x0ec }, // XF86XK_Battery
347 { 0x1008FF94, 0x0ed }, // XF86XK_Bluetooth
348 { 0x1008FF95, 0x0ee }, // XF86XK_WLAN
349 { 0x1008FF96, 0x0ef }, // XF86XK_UWB
350 { 0x1008FE22, 0x0f1 }, // XF86XK_Next_VMode
351 { 0x1008FE23, 0x0f2 }, // XF86XK_Prev_VMode
352 { 0x1008FF07, 0x0f3 }, // XF86XK_MonBrightnessCycle
353 { 0x1008FFB4, 0x0f6 }, // XF86XK_WWAN
354 { 0x1008FFB5, 0x0f7 }, // XF86XK_RFKill
355 { 0x1008FFB2, 0x0f8 }, // XF86XK_AudioMicMute
356 { 0x1008FF9C, 0x173 }, // XF86XK_CycleAngle
357 { 0x1008FFB8, 0x174 }, // XF86XK_FullScreen
358 { 0x1008FF87, 0x189 }, // XF86XK_Video
359 { 0x1008FF20, 0x18d }, // XF86XK_Calendar
360 { 0x1008FF99, 0x19a }, // XF86XK_AudioRandomPlay
361 { 0x1008FF5E, 0x1a1 }, // XF86XK_Game
362 { 0x1008FF8B, 0x1a2 }, // XF86XK_ZoomIn
363 { 0x1008FF8C, 0x1a3 }, // XF86XK_ZoomOut
364 { 0x1008FF89, 0x1a5 }, // XF86XK_Word
365 { 0x1008FF5C, 0x1a7 }, // XF86XK_Excel
366 { 0x1008FF69, 0x1ab }, // XF86XK_News
367 { 0x1008FF8E, 0x1ae }, // XF86XK_Messenger
368 { 0x1008FF61, 0x1b1 }, // XF86XK_LogOff
369 { 0x00000024, 0x1b2 }, // XK_dollar
370 { 0x000020AC, 0x1b3 }, // XK_EuroSign
371 { 0x1008FF9D, 0x1b4 }, // XF86XK_FrameBack
372 { 0x1008FF9E, 0x1b5 }, // XF86XK_FrameForward
373 { 0x0000FFF1, 0x1f1 }, // XK_braille_dot_1
374 { 0x0000FFF2, 0x1f2 }, // XK_braille_dot_2
375 { 0x0000FFF3, 0x1f3 }, // XK_braille_dot_3
376 { 0x0000FFF4, 0x1f4 }, // XK_braille_dot_4
377 { 0x0000FFF5, 0x1f5 }, // XK_braille_dot_5
378 { 0x0000FFF6, 0x1f6 }, // XK_braille_dot_6
379 { 0x0000FFF7, 0x1f7 }, // XK_braille_dot_7
380 { 0x0000FFF8, 0x1f8 }, // XK_braille_dot_8
381 { 0x0000FFF9, 0x1f9 }, // XK_braille_dot_9
382 { 0x0000FFF1, 0x1fa }, // XK_braille_dot_1
383 { 0x1008FFA9, 0x212 }, // XF86XK_TouchpadToggle
384 { 0x1008FFB0, 0x213 }, // XF86XK_TouchpadOn
385 { 0x1008FFB1, 0x214 }, // XF86XK_TouchpadOff
386 { 0x1008FFB7, 0x231 }, // XF86XK_RotationLockToggle
387 { 0x0000FE08, 0x248 }, // XK_ISO_Next_Group
388};
389/* *INDENT-ON* */ // clang-format on
390
391SDL_Scancode SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode)
392{
393 int i;
394 Uint32 linux_keycode = 0;
395
396 // First check our custom list
397 for (i = 0; i < SDL_arraysize(KeySymToSDLScancode); ++i) {
398 if (keysym == KeySymToSDLScancode[i].keysym) {
399 return KeySymToSDLScancode[i].scancode;
400 }
401 }
402
403 if (keysym >= 0x41 && keysym <= 0x5a) {
404 // Normalize alphabetic keysyms to the lowercase form
405 keysym += 0x20;
406 } else if (keysym >= 0x10081000 && keysym <= 0x10081FFF) {
407 /* The rest of the keysyms map to Linux keycodes, so use that mapping
408 * Per xkbcommon-keysyms.h, this is actually a linux keycode.
409 */
410 linux_keycode = (keysym - 0x10081000);
411 }
412 if (!linux_keycode) {
413 // See if this keysym is an exact match in our table
414 i = (keycode - 8);
415 if (i >= 0 && i < SDL_arraysize(LinuxKeycodeKeysyms) && keysym == LinuxKeycodeKeysyms[i]) {
416 linux_keycode = i;
417 } else {
418 // Scan the table for this keysym
419 for (i = 0; i < SDL_arraysize(LinuxKeycodeKeysyms); ++i) {
420 if (keysym == LinuxKeycodeKeysyms[i]) {
421 linux_keycode = i;
422 break;
423 }
424 }
425 }
426 }
427 if (!linux_keycode) {
428 // Scan the extended table for this keysym
429 for (i = 0; i < SDL_arraysize(ExtendedLinuxKeycodeKeysyms); ++i) {
430 if (keysym == ExtendedLinuxKeycodeKeysyms[i].keysym) {
431 linux_keycode = ExtendedLinuxKeycodeKeysyms[i].linux_keycode;
432 break;
433 }
434 }
435 }
436 return SDL_GetScancodeFromTable(SDL_SCANCODE_TABLE_LINUX, linux_keycode);
437}
438
439#endif // SDL_VIDEO_DRIVER_WAYLAND
diff --git a/contrib/SDL-3.2.8/src/events/SDL_keysym_to_scancode_c.h b/contrib/SDL-3.2.8/src/events/SDL_keysym_to_scancode_c.h
new file mode 100644
index 0000000..8d0e214
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_keysym_to_scancode_c.h
@@ -0,0 +1,28 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#ifndef SDL_keysym_to_scancode_c_h_
23#define SDL_keysym_to_scancode_c_h_
24
25// This function only correctly maps letters and numbers for keyboards in US QWERTY layout
26extern SDL_Scancode SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode);
27
28#endif // SDL_keysym_to_scancode_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_mouse.c b/contrib/SDL-3.2.8/src/events/SDL_mouse.c
new file mode 100644
index 0000000..2ea5995
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_mouse.c
@@ -0,0 +1,1673 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// General mouse handling code for SDL
24
25#include "../SDL_hints_c.h"
26#include "../video/SDL_sysvideo.h"
27#include "SDL_events_c.h"
28#include "SDL_mouse_c.h"
29#if defined(SDL_PLATFORM_WINDOWS)
30#include "../core/windows/SDL_windows.h" // For GetDoubleClickTime()
31#endif
32
33// #define DEBUG_MOUSE
34
35#define WARP_EMULATION_THRESHOLD_NS SDL_MS_TO_NS(30)
36
37typedef struct SDL_MouseInstance
38{
39 SDL_MouseID instance_id;
40 char *name;
41} SDL_MouseInstance;
42
43// The mouse state
44static SDL_Mouse SDL_mouse;
45static int SDL_mouse_count;
46static SDL_MouseInstance *SDL_mice;
47
48// for mapping mouse events to touch
49static bool track_mouse_down = false;
50
51static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, bool relative, float x, float y);
52
53static void SDLCALL SDL_MouseDoubleClickTimeChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
54{
55 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
56
57 if (hint && *hint) {
58 mouse->double_click_time = SDL_atoi(hint);
59 } else {
60#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
61 mouse->double_click_time = GetDoubleClickTime();
62#else
63 mouse->double_click_time = 500;
64#endif
65 }
66}
67
68static void SDLCALL SDL_MouseDoubleClickRadiusChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
69{
70 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
71
72 if (hint && *hint) {
73 mouse->double_click_radius = SDL_atoi(hint);
74 } else {
75 mouse->double_click_radius = 32; // 32 pixels seems about right for touch interfaces
76 }
77}
78
79static void SDLCALL SDL_MouseNormalSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
80{
81 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
82
83 if (hint && *hint) {
84 mouse->enable_normal_speed_scale = true;
85 mouse->normal_speed_scale = (float)SDL_atof(hint);
86 } else {
87 mouse->enable_normal_speed_scale = false;
88 mouse->normal_speed_scale = 1.0f;
89 }
90}
91
92static void SDLCALL SDL_MouseRelativeSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
93{
94 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
95
96 if (hint && *hint) {
97 mouse->enable_relative_speed_scale = true;
98 mouse->relative_speed_scale = (float)SDL_atof(hint);
99 } else {
100 mouse->enable_relative_speed_scale = false;
101 mouse->relative_speed_scale = 1.0f;
102 }
103}
104
105static void SDLCALL SDL_MouseRelativeModeCenterChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
106{
107 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
108
109 mouse->relative_mode_center = SDL_GetStringBoolean(hint, true);
110}
111
112static void SDLCALL SDL_MouseRelativeSystemScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
113{
114 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
115
116 mouse->enable_relative_system_scale = SDL_GetStringBoolean(hint, false);
117}
118
119static void SDLCALL SDL_MouseWarpEmulationChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
120{
121 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
122
123 mouse->warp_emulation_hint = SDL_GetStringBoolean(hint, true);
124
125 if (!mouse->warp_emulation_hint && mouse->warp_emulation_active) {
126 SDL_SetRelativeMouseMode(false);
127 mouse->warp_emulation_active = false;
128 }
129}
130
131static void SDLCALL SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
132{
133 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
134
135 mouse->touch_mouse_events = SDL_GetStringBoolean(hint, true);
136}
137
138#ifdef SDL_PLATFORM_VITA
139static void SDLCALL SDL_VitaTouchMouseDeviceChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
140{
141 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
142 if (hint) {
143 switch (*hint) {
144 default:
145 case '0':
146 mouse->vita_touch_mouse_device = 1;
147 break;
148 case '1':
149 mouse->vita_touch_mouse_device = 2;
150 break;
151 case '2':
152 mouse->vita_touch_mouse_device = 3;
153 break;
154 }
155 }
156}
157#endif
158
159static void SDLCALL SDL_MouseTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
160{
161 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
162 bool default_value;
163
164#if defined(SDL_PLATFORM_ANDROID) || (defined(SDL_PLATFORM_IOS) && !defined(SDL_PLATFORM_TVOS))
165 default_value = true;
166#else
167 default_value = false;
168#endif
169 mouse->mouse_touch_events = SDL_GetStringBoolean(hint, default_value);
170
171 if (mouse->mouse_touch_events) {
172 if (!mouse->added_mouse_touch_device) {
173 SDL_AddTouch(SDL_MOUSE_TOUCHID, SDL_TOUCH_DEVICE_DIRECT, "mouse_input");
174 mouse->added_mouse_touch_device = true;
175 }
176 } else {
177 if (mouse->added_mouse_touch_device) {
178 SDL_DelTouch(SDL_MOUSE_TOUCHID);
179 mouse->added_mouse_touch_device = false;
180 }
181 }
182}
183
184static void SDLCALL SDL_PenMouseEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
185{
186 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
187
188 mouse->pen_mouse_events = SDL_GetStringBoolean(hint, true);
189}
190
191static void SDLCALL SDL_PenTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
192{
193 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
194
195 mouse->pen_touch_events = SDL_GetStringBoolean(hint, true);
196
197 if (mouse->pen_touch_events) {
198 if (!mouse->added_pen_touch_device) {
199 SDL_AddTouch(SDL_PEN_TOUCHID, SDL_TOUCH_DEVICE_DIRECT, "pen_input");
200 mouse->added_pen_touch_device = true;
201 }
202 } else {
203 if (mouse->added_pen_touch_device) {
204 SDL_DelTouch(SDL_PEN_TOUCHID);
205 mouse->added_pen_touch_device = false;
206 }
207 }
208}
209
210static void SDLCALL SDL_MouseAutoCaptureChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
211{
212 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
213 bool auto_capture = SDL_GetStringBoolean(hint, true);
214
215 if (auto_capture != mouse->auto_capture) {
216 mouse->auto_capture = auto_capture;
217 SDL_UpdateMouseCapture(false);
218 }
219}
220
221static void SDLCALL SDL_MouseRelativeWarpMotionChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
222{
223 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
224
225 mouse->relative_mode_warp_motion = SDL_GetStringBoolean(hint, false);
226}
227
228static void SDLCALL SDL_MouseRelativeCursorVisibleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
229{
230 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
231
232 mouse->relative_mode_cursor_visible = SDL_GetStringBoolean(hint, false);
233
234 SDL_SetCursor(NULL); // Update cursor visibility
235}
236
237// Public functions
238bool SDL_PreInitMouse(void)
239{
240 SDL_Mouse *mouse = SDL_GetMouse();
241
242 SDL_zerop(mouse);
243
244 SDL_AddHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_TIME,
245 SDL_MouseDoubleClickTimeChanged, mouse);
246
247 SDL_AddHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS,
248 SDL_MouseDoubleClickRadiusChanged, mouse);
249
250 SDL_AddHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
251 SDL_MouseNormalSpeedScaleChanged, mouse);
252
253 SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
254 SDL_MouseRelativeSpeedScaleChanged, mouse);
255
256 SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE,
257 SDL_MouseRelativeSystemScaleChanged, mouse);
258
259 SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER,
260 SDL_MouseRelativeModeCenterChanged, mouse);
261
262 SDL_AddHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE,
263 SDL_MouseWarpEmulationChanged, mouse);
264
265 SDL_AddHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
266 SDL_TouchMouseEventsChanged, mouse);
267
268#ifdef SDL_PLATFORM_VITA
269 SDL_AddHintCallback(SDL_HINT_VITA_TOUCH_MOUSE_DEVICE,
270 SDL_VitaTouchMouseDeviceChanged, mouse);
271#endif
272
273 SDL_AddHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
274 SDL_MouseTouchEventsChanged, mouse);
275
276 SDL_AddHintCallback(SDL_HINT_PEN_MOUSE_EVENTS,
277 SDL_PenMouseEventsChanged, mouse);
278
279 SDL_AddHintCallback(SDL_HINT_PEN_TOUCH_EVENTS,
280 SDL_PenTouchEventsChanged, mouse);
281
282 SDL_AddHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
283 SDL_MouseAutoCaptureChanged, mouse);
284
285 SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION,
286 SDL_MouseRelativeWarpMotionChanged, mouse);
287
288 SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
289 SDL_MouseRelativeCursorVisibleChanged, mouse);
290
291 mouse->was_touch_mouse_events = false; // no touch to mouse movement event pending
292
293 mouse->cursor_shown = true;
294
295 return true;
296}
297
298void SDL_PostInitMouse(void)
299{
300 SDL_Mouse *mouse = SDL_GetMouse();
301
302 /* Create a dummy mouse cursor for video backends that don't support true cursors,
303 * so that mouse grab and focus functionality will work.
304 */
305 if (!mouse->def_cursor) {
306 SDL_Surface *surface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ARGB8888);
307 if (surface) {
308 SDL_memset(surface->pixels, 0, (size_t)surface->h * surface->pitch);
309 SDL_SetDefaultCursor(SDL_CreateColorCursor(surface, 0, 0));
310 SDL_DestroySurface(surface);
311 }
312 }
313}
314
315bool SDL_IsMouse(Uint16 vendor, Uint16 product)
316{
317 // Eventually we'll have a blacklist of devices that enumerate as mice but aren't really
318 return true;
319}
320
321static int SDL_GetMouseIndex(SDL_MouseID mouseID)
322{
323 for (int i = 0; i < SDL_mouse_count; ++i) {
324 if (mouseID == SDL_mice[i].instance_id) {
325 return i;
326 }
327 }
328 return -1;
329}
330
331void SDL_AddMouse(SDL_MouseID mouseID, const char *name, bool send_event)
332{
333 int mouse_index = SDL_GetMouseIndex(mouseID);
334 if (mouse_index >= 0) {
335 // We already know about this mouse
336 return;
337 }
338
339 SDL_assert(mouseID != 0);
340
341 SDL_MouseInstance *mice = (SDL_MouseInstance *)SDL_realloc(SDL_mice, (SDL_mouse_count + 1) * sizeof(*mice));
342 if (!mice) {
343 return;
344 }
345 SDL_MouseInstance *instance = &mice[SDL_mouse_count];
346 instance->instance_id = mouseID;
347 instance->name = SDL_strdup(name ? name : "");
348 SDL_mice = mice;
349 ++SDL_mouse_count;
350
351 if (send_event) {
352 SDL_Event event;
353 SDL_zero(event);
354 event.type = SDL_EVENT_MOUSE_ADDED;
355 event.mdevice.which = mouseID;
356 SDL_PushEvent(&event);
357 }
358}
359
360void SDL_RemoveMouse(SDL_MouseID mouseID, bool send_event)
361{
362 int mouse_index = SDL_GetMouseIndex(mouseID);
363 if (mouse_index < 0) {
364 // We don't know about this mouse
365 return;
366 }
367
368 SDL_free(SDL_mice[mouse_index].name);
369
370 if (mouse_index != SDL_mouse_count - 1) {
371 SDL_memmove(&SDL_mice[mouse_index], &SDL_mice[mouse_index + 1], (SDL_mouse_count - mouse_index - 1) * sizeof(SDL_mice[mouse_index]));
372 }
373 --SDL_mouse_count;
374
375 // Remove any mouse input sources for this mouseID
376 SDL_Mouse *mouse = SDL_GetMouse();
377 for (int i = 0; i < mouse->num_sources; ++i) {
378 SDL_MouseInputSource *source = &mouse->sources[i];
379 if (source->mouseID == mouseID) {
380 SDL_free(source->clickstate);
381 if (i != mouse->num_sources - 1) {
382 SDL_memmove(&mouse->sources[i], &mouse->sources[i + 1], (mouse->num_sources - i - 1) * sizeof(mouse->sources[i]));
383 }
384 --mouse->num_sources;
385 break;
386 }
387 }
388
389 if (send_event) {
390 SDL_Event event;
391 SDL_zero(event);
392 event.type = SDL_EVENT_MOUSE_REMOVED;
393 event.mdevice.which = mouseID;
394 SDL_PushEvent(&event);
395 }
396}
397
398bool SDL_HasMouse(void)
399{
400 return (SDL_mouse_count > 0);
401}
402
403SDL_MouseID *SDL_GetMice(int *count)
404{
405 int i;
406 SDL_MouseID *mice;
407
408 mice = (SDL_JoystickID *)SDL_malloc((SDL_mouse_count + 1) * sizeof(*mice));
409 if (mice) {
410 if (count) {
411 *count = SDL_mouse_count;
412 }
413
414 for (i = 0; i < SDL_mouse_count; ++i) {
415 mice[i] = SDL_mice[i].instance_id;
416 }
417 mice[i] = 0;
418 } else {
419 if (count) {
420 *count = 0;
421 }
422 }
423
424 return mice;
425}
426
427const char *SDL_GetMouseNameForID(SDL_MouseID instance_id)
428{
429 int mouse_index = SDL_GetMouseIndex(instance_id);
430 if (mouse_index < 0) {
431 SDL_SetError("Mouse %" SDL_PRIu32 " not found", instance_id);
432 return NULL;
433 }
434 return SDL_GetPersistentString(SDL_mice[mouse_index].name);
435}
436
437void SDL_SetDefaultCursor(SDL_Cursor *cursor)
438{
439 SDL_Mouse *mouse = SDL_GetMouse();
440
441 if (cursor == mouse->def_cursor) {
442 return;
443 }
444
445 if (mouse->def_cursor) {
446 SDL_Cursor *default_cursor = mouse->def_cursor;
447 SDL_Cursor *prev, *curr;
448
449 if (mouse->cur_cursor == mouse->def_cursor) {
450 mouse->cur_cursor = NULL;
451 }
452 mouse->def_cursor = NULL;
453
454 for (prev = NULL, curr = mouse->cursors; curr;
455 prev = curr, curr = curr->next) {
456 if (curr == default_cursor) {
457 if (prev) {
458 prev->next = curr->next;
459 } else {
460 mouse->cursors = curr->next;
461 }
462
463 break;
464 }
465 }
466
467 if (mouse->FreeCursor && default_cursor->internal) {
468 mouse->FreeCursor(default_cursor);
469 } else {
470 SDL_free(default_cursor);
471 }
472 }
473
474 mouse->def_cursor = cursor;
475
476 if (!mouse->cur_cursor) {
477 SDL_SetCursor(cursor);
478 }
479}
480
481SDL_SystemCursor SDL_GetDefaultSystemCursor(void)
482{
483 SDL_SystemCursor id = SDL_SYSTEM_CURSOR_DEFAULT;
484 const char *value = SDL_GetHint(SDL_HINT_MOUSE_DEFAULT_SYSTEM_CURSOR);
485 if (value) {
486 int index = SDL_atoi(value);
487 if (0 <= index && index < SDL_SYSTEM_CURSOR_COUNT) {
488 id = (SDL_SystemCursor)index;
489 }
490 }
491 return id;
492}
493
494SDL_Mouse *SDL_GetMouse(void)
495{
496 return &SDL_mouse;
497}
498
499static SDL_MouseButtonFlags SDL_GetMouseButtonState(SDL_Mouse *mouse, SDL_MouseID mouseID, bool include_touch)
500{
501 int i;
502 SDL_MouseButtonFlags buttonstate = 0;
503
504 for (i = 0; i < mouse->num_sources; ++i) {
505 if (mouseID == SDL_GLOBAL_MOUSE_ID || mouseID == SDL_TOUCH_MOUSEID) {
506 if (include_touch || mouse->sources[i].mouseID != SDL_TOUCH_MOUSEID) {
507 buttonstate |= mouse->sources[i].buttonstate;
508 }
509 } else {
510 if (mouseID == mouse->sources[i].mouseID) {
511 buttonstate |= mouse->sources[i].buttonstate;
512 break;
513 }
514 }
515 }
516 return buttonstate;
517}
518
519SDL_Window *SDL_GetMouseFocus(void)
520{
521 SDL_Mouse *mouse = SDL_GetMouse();
522
523 return mouse->focus;
524}
525
526/* TODO RECONNECT: Hello from the Wayland video driver!
527 * This was once removed from SDL, but it's been added back in comment form
528 * because we will need it when Wayland adds compositor reconnect support.
529 * If you need this before we do, great! Otherwise, leave this alone, we'll
530 * uncomment it at the right time.
531 * -flibit
532 */
533#if 0
534void SDL_ResetMouse(void)
535{
536 SDL_Mouse *mouse = SDL_GetMouse();
537 Uint32 buttonState = SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, false);
538 int i;
539
540 for (i = 1; i <= sizeof(buttonState)*8; ++i) {
541 if (buttonState & SDL_BUTTON_MASK(i)) {
542 SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, i, false);
543 }
544 }
545 SDL_assert(SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, false) == 0);
546}
547#endif // 0
548
549void SDL_SetMouseFocus(SDL_Window *window)
550{
551 SDL_Mouse *mouse = SDL_GetMouse();
552
553 if (mouse->focus == window) {
554 return;
555 }
556
557 /* Actually, this ends up being a bad idea, because most operating
558 systems have an implicit grab when you press the mouse button down
559 so you can drag things out of the window and then get the mouse up
560 when it happens. So, #if 0...
561 */
562#if 0
563 if (mouse->focus && !window) {
564 // We won't get anymore mouse messages, so reset mouse state
565 SDL_ResetMouse();
566 }
567#endif
568
569 // See if the current window has lost focus
570 if (mouse->focus) {
571 SDL_SendWindowEvent(mouse->focus, SDL_EVENT_WINDOW_MOUSE_LEAVE, 0, 0);
572 }
573
574 mouse->focus = window;
575 mouse->has_position = false;
576
577 if (mouse->focus) {
578 SDL_SendWindowEvent(mouse->focus, SDL_EVENT_WINDOW_MOUSE_ENTER, 0, 0);
579 }
580
581 // Update cursor visibility
582 SDL_SetCursor(NULL);
583}
584
585bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y)
586{
587 if (!window) {
588 return false;
589 }
590
591 if (window && !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
592 if (x < 0.0f || y < 0.0f || x >= (float)window->w || y >= (float)window->h) {
593 return false;
594 }
595 }
596 return true;
597}
598
599// Check to see if we need to synthesize focus events
600static bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint32 buttonstate, bool send_mouse_motion)
601{
602 SDL_Mouse *mouse = SDL_GetMouse();
603 bool inWindow = SDL_MousePositionInWindow(window, x, y);
604
605 if (!inWindow) {
606 if (window == mouse->focus) {
607#ifdef DEBUG_MOUSE
608 SDL_Log("Mouse left window, synthesizing move & focus lost event");
609#endif
610 if (send_mouse_motion) {
611 SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, x, y);
612 }
613 SDL_SetMouseFocus(NULL);
614 }
615 return false;
616 }
617
618 if (window != mouse->focus) {
619#ifdef DEBUG_MOUSE
620 SDL_Log("Mouse entered window, synthesizing focus gain & move event");
621#endif
622 SDL_SetMouseFocus(window);
623 if (send_mouse_motion) {
624 SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, x, y);
625 }
626 }
627 return true;
628}
629
630void SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, bool relative, float x, float y)
631{
632 if (window && !relative) {
633 SDL_Mouse *mouse = SDL_GetMouse();
634 if (!SDL_UpdateMouseFocus(window, x, y, SDL_GetMouseButtonState(mouse, mouseID, true), (mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID))) {
635 return;
636 }
637 }
638
639 SDL_PrivateSendMouseMotion(timestamp, window, mouseID, relative, x, y);
640}
641
642static void ConstrainMousePosition(SDL_Mouse *mouse, SDL_Window *window, float *x, float *y)
643{
644 /* make sure that the pointers find themselves inside the windows,
645 unless we have the mouse captured. */
646 if (window && !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
647 int x_min = 0, x_max = window->w - 1;
648 int y_min = 0, y_max = window->h - 1;
649 const SDL_Rect *confine = SDL_GetWindowMouseRect(window);
650
651 if (confine) {
652 SDL_Rect window_rect;
653 SDL_Rect mouse_rect;
654
655 window_rect.x = 0;
656 window_rect.y = 0;
657 window_rect.w = x_max + 1;
658 window_rect.h = y_max + 1;
659 if (SDL_GetRectIntersection(confine, &window_rect, &mouse_rect)) {
660 x_min = mouse_rect.x;
661 y_min = mouse_rect.y;
662 x_max = x_min + mouse_rect.w - 1;
663 y_max = y_min + mouse_rect.h - 1;
664 }
665 }
666
667 if (*x >= (float)(x_max + 1)) {
668 *x = SDL_max((float)x_max, mouse->last_x);
669 }
670 if (*x < (float)x_min) {
671 *x = (float)x_min;
672 }
673
674 if (*y >= (float)(y_max + 1)) {
675 *y = SDL_max((float)y_max, mouse->last_y);
676 }
677 if (*y < (float)y_min) {
678 *y = (float)y_min;
679 }
680 }
681}
682
683static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, bool relative, float x, float y)
684{
685 SDL_Mouse *mouse = SDL_GetMouse();
686 float xrel = 0.0f;
687 float yrel = 0.0f;
688 bool window_is_relative = mouse->focus && (mouse->focus->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE);
689
690 // SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events
691 if (mouse->mouse_touch_events) {
692 if (mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID && !relative && track_mouse_down) {
693 if (window) {
694 float normalized_x = x / (float)window->w;
695 float normalized_y = y / (float)window->h;
696 SDL_SendTouchMotion(timestamp, SDL_MOUSE_TOUCHID, SDL_BUTTON_LEFT, window, normalized_x, normalized_y, 1.0f);
697 }
698 }
699 }
700
701 // SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer
702 if (!mouse->touch_mouse_events && mouseID == SDL_TOUCH_MOUSEID) {
703 return;
704 }
705
706 if (relative) {
707 if (mouse->relative_mode) {
708 if (mouse->enable_relative_system_scale) {
709 if (mouse->ApplySystemScale) {
710 mouse->ApplySystemScale(mouse->system_scale_data, timestamp, window, mouseID, &x, &y);
711 }
712 }
713 if (mouse->enable_relative_speed_scale) {
714 x *= mouse->relative_speed_scale;
715 y *= mouse->relative_speed_scale;
716 }
717 } else {
718 if (mouse->enable_normal_speed_scale) {
719 x *= mouse->normal_speed_scale;
720 y *= mouse->normal_speed_scale;
721 }
722 }
723 xrel = x;
724 yrel = y;
725 x = (mouse->last_x + xrel);
726 y = (mouse->last_y + yrel);
727 ConstrainMousePosition(mouse, window, &x, &y);
728 } else {
729 ConstrainMousePosition(mouse, window, &x, &y);
730 if (mouse->has_position) {
731 xrel = x - mouse->last_x;
732 yrel = y - mouse->last_y;
733 }
734 }
735
736 if (mouse->has_position && xrel == 0.0f && yrel == 0.0f) { // Drop events that don't change state
737#ifdef DEBUG_MOUSE
738 SDL_Log("Mouse event didn't change state - dropped!");
739#endif
740 return;
741 }
742
743 // Ignore relative motion positioning the first touch
744 if (mouseID == SDL_TOUCH_MOUSEID && !SDL_GetMouseButtonState(mouse, mouseID, true)) {
745 xrel = 0.0f;
746 yrel = 0.0f;
747 }
748
749 // modify internal state
750 {
751 mouse->x_accu += xrel;
752 mouse->y_accu += yrel;
753
754 if (relative && mouse->has_position) {
755 mouse->x += xrel;
756 mouse->y += yrel;
757 ConstrainMousePosition(mouse, window, &mouse->x, &mouse->y);
758 } else {
759 mouse->x = x;
760 mouse->y = y;
761 }
762 mouse->has_position = true;
763
764 // Use unclamped values if we're getting events outside the window
765 mouse->last_x = relative ? mouse->x : x;
766 mouse->last_y = relative ? mouse->y : y;
767
768 mouse->click_motion_x += xrel;
769 mouse->click_motion_y += yrel;
770 }
771
772 // Move the mouse cursor, if needed
773 if (mouse->cursor_shown && !mouse->relative_mode &&
774 mouse->MoveCursor && mouse->cur_cursor) {
775 mouse->MoveCursor(mouse->cur_cursor);
776 }
777
778 // Post the event, if desired
779 if (SDL_EventEnabled(SDL_EVENT_MOUSE_MOTION)) {
780 if ((!mouse->relative_mode || mouse->warp_emulation_active) && mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID) {
781 // We're not in relative mode, so all mouse events are global mouse events
782 mouseID = SDL_GLOBAL_MOUSE_ID;
783 }
784
785 if (!relative && window_is_relative) {
786 if (!mouse->relative_mode_warp_motion) {
787 return;
788 }
789 xrel = 0.0f;
790 yrel = 0.0f;
791 }
792
793 SDL_Event event;
794 event.type = SDL_EVENT_MOUSE_MOTION;
795 event.common.timestamp = timestamp;
796 event.motion.windowID = mouse->focus ? mouse->focus->id : 0;
797 event.motion.which = mouseID;
798 // Set us pending (or clear during a normal mouse movement event) as having triggered
799 mouse->was_touch_mouse_events = (mouseID == SDL_TOUCH_MOUSEID);
800 event.motion.state = SDL_GetMouseButtonState(mouse, mouseID, true);
801 event.motion.x = mouse->x;
802 event.motion.y = mouse->y;
803 event.motion.xrel = xrel;
804 event.motion.yrel = yrel;
805 SDL_PushEvent(&event);
806 }
807}
808
809static SDL_MouseInputSource *GetMouseInputSource(SDL_Mouse *mouse, SDL_MouseID mouseID, bool down, Uint8 button)
810{
811 SDL_MouseInputSource *source, *match = NULL, *sources;
812 int i;
813
814 for (i = 0; i < mouse->num_sources; ++i) {
815 source = &mouse->sources[i];
816 if (source->mouseID == mouseID) {
817 match = source;
818 break;
819 }
820 }
821
822 if (!down && (!match || !(match->buttonstate & SDL_BUTTON_MASK(button)))) {
823 /* This might be a button release from a transition between mouse messages and raw input.
824 * See if there's another mouse source that already has that button down and use that.
825 */
826 for (i = 0; i < mouse->num_sources; ++i) {
827 source = &mouse->sources[i];
828 if ((source->buttonstate & SDL_BUTTON_MASK(button))) {
829 match = source;
830 break;
831 }
832 }
833 }
834 if (match) {
835 return match;
836 }
837
838 sources = (SDL_MouseInputSource *)SDL_realloc(mouse->sources, (mouse->num_sources + 1) * sizeof(*mouse->sources));
839 if (sources) {
840 mouse->sources = sources;
841 ++mouse->num_sources;
842 source = &sources[mouse->num_sources - 1];
843 SDL_zerop(source);
844 source->mouseID = mouseID;
845 return source;
846 }
847 return NULL;
848}
849
850static SDL_MouseClickState *GetMouseClickState(SDL_MouseInputSource *source, Uint8 button)
851{
852 if (button >= source->num_clickstates) {
853 int i, count = button + 1;
854 SDL_MouseClickState *clickstate = (SDL_MouseClickState *)SDL_realloc(source->clickstate, count * sizeof(*source->clickstate));
855 if (!clickstate) {
856 return NULL;
857 }
858 source->clickstate = clickstate;
859
860 for (i = source->num_clickstates; i < count; ++i) {
861 SDL_zero(source->clickstate[i]);
862 }
863 source->num_clickstates = count;
864 }
865 return &source->clickstate[button];
866}
867
868static void SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down, int clicks)
869{
870 SDL_Mouse *mouse = SDL_GetMouse();
871 SDL_EventType type;
872 Uint32 buttonstate;
873 SDL_MouseInputSource *source;
874
875 source = GetMouseInputSource(mouse, mouseID, down, button);
876 if (!source) {
877 return;
878 }
879 buttonstate = source->buttonstate;
880
881 // SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events
882 if (mouse->mouse_touch_events) {
883 if (mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID && button == SDL_BUTTON_LEFT) {
884 if (down) {
885 track_mouse_down = true;
886 } else {
887 track_mouse_down = false;
888 }
889 if (window) {
890 type = track_mouse_down ? SDL_EVENT_FINGER_DOWN : SDL_EVENT_FINGER_UP;
891 float normalized_x = mouse->x / (float)window->w;
892 float normalized_y = mouse->y / (float)window->h;
893 SDL_SendTouch(timestamp, SDL_MOUSE_TOUCHID, SDL_BUTTON_LEFT, window, type, normalized_x, normalized_y, 1.0f);
894 }
895 }
896 }
897
898 // SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer
899 if (mouse->touch_mouse_events == 0) {
900 if (mouseID == SDL_TOUCH_MOUSEID) {
901 return;
902 }
903 }
904
905 // Figure out which event to perform
906 if (down) {
907 type = SDL_EVENT_MOUSE_BUTTON_DOWN;
908 buttonstate |= SDL_BUTTON_MASK(button);
909 } else {
910 type = SDL_EVENT_MOUSE_BUTTON_UP;
911 buttonstate &= ~SDL_BUTTON_MASK(button);
912 }
913
914 // We do this after calculating buttonstate so button presses gain focus
915 if (window && down) {
916 SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, true);
917 }
918
919 if (buttonstate == source->buttonstate) {
920 // Ignore this event, no state change
921 return;
922 }
923 source->buttonstate = buttonstate;
924
925 if (clicks < 0) {
926 SDL_MouseClickState *clickstate = GetMouseClickState(source, button);
927 if (clickstate) {
928 if (down) {
929 Uint64 now = SDL_GetTicks();
930
931 if (now >= (clickstate->last_timestamp + mouse->double_click_time) ||
932 SDL_fabs(mouse->click_motion_x - clickstate->click_motion_x) > mouse->double_click_radius ||
933 SDL_fabs(mouse->click_motion_y - clickstate->click_motion_y) > mouse->double_click_radius) {
934 clickstate->click_count = 0;
935 }
936 clickstate->last_timestamp = now;
937 clickstate->click_motion_x = mouse->click_motion_x;
938 clickstate->click_motion_y = mouse->click_motion_y;
939 if (clickstate->click_count < 255) {
940 ++clickstate->click_count;
941 }
942 }
943 clicks = clickstate->click_count;
944 } else {
945 clicks = 1;
946 }
947 }
948
949 // Post the event, if desired
950 if (SDL_EventEnabled(type)) {
951 if ((!mouse->relative_mode || mouse->warp_emulation_active) && mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID) {
952 // We're not in relative mode, so all mouse events are global mouse events
953 mouseID = SDL_GLOBAL_MOUSE_ID;
954 } else {
955 mouseID = source->mouseID;
956 }
957
958 SDL_Event event;
959 event.type = type;
960 event.common.timestamp = timestamp;
961 event.button.windowID = mouse->focus ? mouse->focus->id : 0;
962 event.button.which = mouseID;
963 event.button.down = down;
964 event.button.button = button;
965 event.button.clicks = (Uint8)SDL_min(clicks, 255);
966 event.button.x = mouse->x;
967 event.button.y = mouse->y;
968 SDL_PushEvent(&event);
969 }
970
971 // We do this after dispatching event so button releases can lose focus
972 if (window && !down) {
973 SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, true);
974 }
975
976 // Automatically capture the mouse while buttons are pressed
977 if (mouse->auto_capture) {
978 SDL_UpdateMouseCapture(false);
979 }
980}
981
982void SDL_SendMouseButtonClicks(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down, int clicks)
983{
984 clicks = SDL_max(clicks, 0);
985 SDL_PrivateSendMouseButton(timestamp, window, mouseID, button, down, clicks);
986}
987
988void SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down)
989{
990 SDL_PrivateSendMouseButton(timestamp, window, mouseID, button, down, -1);
991}
992
993void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
994{
995 SDL_Mouse *mouse = SDL_GetMouse();
996
997 if (window) {
998 SDL_SetMouseFocus(window);
999 }
1000
1001 if (x == 0.0f && y == 0.0f) {
1002 return;
1003 }
1004
1005 // Post the event, if desired
1006 if (SDL_EventEnabled(SDL_EVENT_MOUSE_WHEEL)) {
1007 if (!mouse->relative_mode || mouse->warp_emulation_active) {
1008 // We're not in relative mode, so all mouse events are global mouse events
1009 mouseID = SDL_GLOBAL_MOUSE_ID;
1010 }
1011
1012 SDL_Event event;
1013 event.type = SDL_EVENT_MOUSE_WHEEL;
1014 event.common.timestamp = timestamp;
1015 event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
1016 event.wheel.which = mouseID;
1017 event.wheel.x = x;
1018 event.wheel.y = y;
1019 event.wheel.direction = direction;
1020 event.wheel.mouse_x = mouse->x;
1021 event.wheel.mouse_y = mouse->y;
1022 SDL_PushEvent(&event);
1023 }
1024}
1025
1026void SDL_QuitMouse(void)
1027{
1028 SDL_Cursor *cursor, *next;
1029 SDL_Mouse *mouse = SDL_GetMouse();
1030
1031 if (mouse->added_mouse_touch_device) {
1032 SDL_DelTouch(SDL_MOUSE_TOUCHID);
1033 }
1034
1035 if (mouse->added_pen_touch_device) {
1036 SDL_DelTouch(SDL_PEN_TOUCHID);
1037 }
1038
1039 if (mouse->CaptureMouse) {
1040 SDL_CaptureMouse(false);
1041 SDL_UpdateMouseCapture(true);
1042 }
1043 SDL_SetRelativeMouseMode(false);
1044 SDL_ShowCursor();
1045
1046 if (mouse->def_cursor) {
1047 SDL_SetDefaultCursor(NULL);
1048 }
1049
1050 cursor = mouse->cursors;
1051 while (cursor) {
1052 next = cursor->next;
1053 SDL_DestroyCursor(cursor);
1054 cursor = next;
1055 }
1056 mouse->cursors = NULL;
1057 mouse->cur_cursor = NULL;
1058
1059 if (mouse->sources) {
1060 for (int i = 0; i < mouse->num_sources; ++i) {
1061 SDL_MouseInputSource *source = &mouse->sources[i];
1062 SDL_free(source->clickstate);
1063 }
1064 SDL_free(mouse->sources);
1065 mouse->sources = NULL;
1066 }
1067 mouse->num_sources = 0;
1068
1069 SDL_RemoveHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_TIME,
1070 SDL_MouseDoubleClickTimeChanged, mouse);
1071
1072 SDL_RemoveHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS,
1073 SDL_MouseDoubleClickRadiusChanged, mouse);
1074
1075 SDL_RemoveHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
1076 SDL_MouseNormalSpeedScaleChanged, mouse);
1077
1078 SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
1079 SDL_MouseRelativeSpeedScaleChanged, mouse);
1080
1081 SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE,
1082 SDL_MouseRelativeSystemScaleChanged, mouse);
1083
1084 SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER,
1085 SDL_MouseRelativeModeCenterChanged, mouse);
1086
1087 SDL_RemoveHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE,
1088 SDL_MouseWarpEmulationChanged, mouse);
1089
1090 SDL_RemoveHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
1091 SDL_TouchMouseEventsChanged, mouse);
1092
1093 SDL_RemoveHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
1094 SDL_MouseTouchEventsChanged, mouse);
1095
1096 SDL_RemoveHintCallback(SDL_HINT_PEN_MOUSE_EVENTS,
1097 SDL_PenMouseEventsChanged, mouse);
1098
1099 SDL_RemoveHintCallback(SDL_HINT_PEN_TOUCH_EVENTS,
1100 SDL_PenTouchEventsChanged, mouse);
1101
1102 SDL_RemoveHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
1103 SDL_MouseAutoCaptureChanged, mouse);
1104
1105 SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION,
1106 SDL_MouseRelativeWarpMotionChanged, mouse);
1107
1108 SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
1109 SDL_MouseRelativeCursorVisibleChanged, mouse);
1110
1111 for (int i = SDL_mouse_count; i--; ) {
1112 SDL_RemoveMouse(SDL_mice[i].instance_id, false);
1113 }
1114 SDL_free(SDL_mice);
1115 SDL_mice = NULL;
1116}
1117
1118SDL_MouseButtonFlags SDL_GetMouseState(float *x, float *y)
1119{
1120 SDL_Mouse *mouse = SDL_GetMouse();
1121
1122 if (x) {
1123 *x = mouse->x;
1124 }
1125 if (y) {
1126 *y = mouse->y;
1127 }
1128 return SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, true);
1129}
1130
1131SDL_MouseButtonFlags SDL_GetRelativeMouseState(float *x, float *y)
1132{
1133 SDL_Mouse *mouse = SDL_GetMouse();
1134
1135 if (x) {
1136 *x = mouse->x_accu;
1137 }
1138 if (y) {
1139 *y = mouse->y_accu;
1140 }
1141 mouse->x_accu = 0.0f;
1142 mouse->y_accu = 0.0f;
1143 return SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, true);
1144}
1145
1146SDL_MouseButtonFlags SDL_GetGlobalMouseState(float *x, float *y)
1147{
1148 SDL_Mouse *mouse = SDL_GetMouse();
1149
1150 if (mouse->GetGlobalMouseState) {
1151 float tmpx, tmpy;
1152
1153 // make sure these are never NULL for the backend implementations...
1154 if (!x) {
1155 x = &tmpx;
1156 }
1157 if (!y) {
1158 y = &tmpy;
1159 }
1160
1161 *x = *y = 0.0f;
1162
1163 return mouse->GetGlobalMouseState(x, y);
1164 } else {
1165 return SDL_GetMouseState(x, y);
1166 }
1167}
1168
1169void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, bool ignore_relative_mode)
1170{
1171 SDL_Mouse *mouse = SDL_GetMouse();
1172
1173 if (!window) {
1174 window = mouse->focus;
1175 }
1176
1177 if (!window) {
1178 return;
1179 }
1180
1181 if ((window->flags & SDL_WINDOW_MINIMIZED) == SDL_WINDOW_MINIMIZED) {
1182 return;
1183 }
1184
1185 // Ignore the previous position when we warp
1186 mouse->last_x = x;
1187 mouse->last_y = y;
1188 mouse->has_position = false;
1189
1190 if (mouse->relative_mode && !ignore_relative_mode) {
1191 /* 2.0.22 made warping in relative mode actually functional, which
1192 * surprised many applications that weren't expecting the additional
1193 * mouse motion.
1194 *
1195 * So for now, warping in relative mode adjusts the absolution position
1196 * but doesn't generate motion events, unless SDL_HINT_MOUSE_RELATIVE_WARP_MOTION is set.
1197 */
1198 if (!mouse->relative_mode_warp_motion) {
1199 mouse->x = x;
1200 mouse->y = y;
1201 mouse->has_position = true;
1202 return;
1203 }
1204 }
1205
1206 if (mouse->WarpMouse && !mouse->relative_mode) {
1207 mouse->WarpMouse(window, x, y);
1208 } else {
1209 SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, x, y);
1210 }
1211}
1212
1213void SDL_DisableMouseWarpEmulation(void)
1214{
1215 SDL_Mouse *mouse = SDL_GetMouse();
1216
1217 if (mouse->warp_emulation_active) {
1218 SDL_SetRelativeMouseMode(false);
1219 }
1220
1221 mouse->warp_emulation_prohibited = true;
1222}
1223
1224static void SDL_MaybeEnableWarpEmulation(SDL_Window *window, float x, float y)
1225{
1226 SDL_Mouse *mouse = SDL_GetMouse();
1227
1228 if (!mouse->warp_emulation_prohibited && mouse->warp_emulation_hint && !mouse->cursor_shown && !mouse->warp_emulation_active) {
1229 if (!window) {
1230 window = mouse->focus;
1231 }
1232
1233 if (window) {
1234 const float cx = window->w / 2.f;
1235 const float cy = window->h / 2.f;
1236 if (x >= SDL_floorf(cx) && x <= SDL_ceilf(cx) &&
1237 y >= SDL_floorf(cy) && y <= SDL_ceilf(cy)) {
1238
1239 // Require two consecutive warps to the center within a certain timespan to enter warp emulation mode.
1240 const Uint64 now = SDL_GetTicksNS();
1241 if (now - mouse->last_center_warp_time_ns < WARP_EMULATION_THRESHOLD_NS) {
1242 if (SDL_SetRelativeMouseMode(true)) {
1243 mouse->warp_emulation_active = true;
1244 }
1245 }
1246
1247 mouse->last_center_warp_time_ns = now;
1248 return;
1249 }
1250 }
1251
1252 mouse->last_center_warp_time_ns = 0;
1253 }
1254}
1255
1256void SDL_WarpMouseInWindow(SDL_Window *window, float x, float y)
1257{
1258 SDL_Mouse *mouse = SDL_GetMouse();
1259 SDL_MaybeEnableWarpEmulation(window, x, y);
1260
1261 SDL_PerformWarpMouseInWindow(window, x, y, mouse->warp_emulation_active);
1262}
1263
1264bool SDL_WarpMouseGlobal(float x, float y)
1265{
1266 SDL_Mouse *mouse = SDL_GetMouse();
1267
1268 if (mouse->WarpMouseGlobal) {
1269 return mouse->WarpMouseGlobal(x, y);
1270 }
1271
1272 return SDL_Unsupported();
1273}
1274
1275bool SDL_SetRelativeMouseMode(bool enabled)
1276{
1277 SDL_Mouse *mouse = SDL_GetMouse();
1278 SDL_Window *focusWindow = SDL_GetKeyboardFocus();
1279
1280 if (!enabled) {
1281 // If warps were being emulated, reset the flag.
1282 mouse->warp_emulation_active = false;
1283 }
1284
1285 if (enabled == mouse->relative_mode) {
1286 return true;
1287 }
1288
1289 // Set the relative mode
1290 if (!mouse->SetRelativeMouseMode || !mouse->SetRelativeMouseMode(enabled)) {
1291 if (enabled) {
1292 return SDL_SetError("No relative mode implementation available");
1293 }
1294 }
1295 mouse->relative_mode = enabled;
1296
1297 if (enabled) {
1298 // Update cursor visibility before we potentially warp the mouse
1299 SDL_SetCursor(NULL);
1300 }
1301
1302 if (enabled && focusWindow) {
1303 SDL_SetMouseFocus(focusWindow);
1304 }
1305
1306 if (focusWindow) {
1307 SDL_UpdateWindowGrab(focusWindow);
1308
1309 // Put the cursor back to where the application expects it
1310 if (!enabled) {
1311 SDL_PerformWarpMouseInWindow(focusWindow, mouse->x, mouse->y, true);
1312 }
1313
1314 SDL_UpdateMouseCapture(false);
1315 }
1316
1317 if (!enabled) {
1318 // Update cursor visibility after we restore the mouse position
1319 SDL_SetCursor(NULL);
1320 }
1321
1322 // Flush pending mouse motion - ideally we would pump events, but that's not always safe
1323 SDL_FlushEvent(SDL_EVENT_MOUSE_MOTION);
1324
1325 return true;
1326}
1327
1328bool SDL_GetRelativeMouseMode(void)
1329{
1330 SDL_Mouse *mouse = SDL_GetMouse();
1331
1332 return mouse->relative_mode;
1333}
1334
1335void SDL_UpdateRelativeMouseMode(void)
1336{
1337 SDL_Mouse *mouse = SDL_GetMouse();
1338 SDL_Window *focus = SDL_GetKeyboardFocus();
1339 bool relative_mode = (focus && (focus->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE));
1340
1341 if (relative_mode != mouse->relative_mode) {
1342 SDL_SetRelativeMouseMode(relative_mode);
1343 }
1344}
1345
1346bool SDL_UpdateMouseCapture(bool force_release)
1347{
1348 SDL_Mouse *mouse = SDL_GetMouse();
1349 SDL_Window *capture_window = NULL;
1350
1351 if (!mouse->CaptureMouse) {
1352 return true;
1353 }
1354
1355 if (!force_release) {
1356 if (SDL_GetMessageBoxCount() == 0 &&
1357 (mouse->capture_desired || (mouse->auto_capture && SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, false) != 0))) {
1358 if (!mouse->relative_mode) {
1359 capture_window = mouse->focus;
1360 }
1361 }
1362 }
1363
1364 if (capture_window != mouse->capture_window) {
1365 /* We can get here recursively on Windows, so make sure we complete
1366 * all of the window state operations before we change the capture state
1367 * (e.g. https://github.com/libsdl-org/SDL/pull/5608)
1368 */
1369 SDL_Window *previous_capture = mouse->capture_window;
1370
1371 if (previous_capture) {
1372 previous_capture->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
1373 }
1374
1375 if (capture_window) {
1376 capture_window->flags |= SDL_WINDOW_MOUSE_CAPTURE;
1377 }
1378
1379 mouse->capture_window = capture_window;
1380
1381 if (!mouse->CaptureMouse(capture_window)) {
1382 // CaptureMouse() will have set an error, just restore the state
1383 if (previous_capture) {
1384 previous_capture->flags |= SDL_WINDOW_MOUSE_CAPTURE;
1385 }
1386 if (capture_window) {
1387 capture_window->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
1388 }
1389 mouse->capture_window = previous_capture;
1390
1391 return false;
1392 }
1393 }
1394 return true;
1395}
1396
1397bool SDL_CaptureMouse(bool enabled)
1398{
1399 SDL_Mouse *mouse = SDL_GetMouse();
1400
1401 if (!mouse->CaptureMouse) {
1402 return SDL_Unsupported();
1403 }
1404
1405#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
1406 /* Windows mouse capture is tied to the current thread, and must be called
1407 * from the thread that created the window being captured. Since we update
1408 * the mouse capture state from the event processing, any application state
1409 * changes must be processed on that thread as well.
1410 */
1411 if (!SDL_OnVideoThread()) {
1412 return SDL_SetError("SDL_CaptureMouse() must be called on the main thread");
1413 }
1414#endif // defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
1415
1416 if (enabled && SDL_GetKeyboardFocus() == NULL) {
1417 return SDL_SetError("No window has focus");
1418 }
1419 mouse->capture_desired = enabled;
1420
1421 return SDL_UpdateMouseCapture(false);
1422}
1423
1424SDL_Cursor *SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, int hot_x, int hot_y)
1425{
1426 SDL_Surface *surface;
1427 SDL_Cursor *cursor;
1428 int x, y;
1429 Uint32 *pixel;
1430 Uint8 datab = 0, maskb = 0;
1431 const Uint32 black = 0xFF000000;
1432 const Uint32 white = 0xFFFFFFFF;
1433 const Uint32 transparent = 0x00000000;
1434#if defined(SDL_PLATFORM_WIN32)
1435 // Only Windows backend supports inverted pixels in mono cursors.
1436 const Uint32 inverted = 0x00FFFFFF;
1437#else
1438 const Uint32 inverted = 0xFF000000;
1439#endif // defined(SDL_PLATFORM_WIN32)
1440
1441 // Make sure the width is a multiple of 8
1442 w = ((w + 7) & ~7);
1443
1444 // Create the surface from a bitmap
1445 surface = SDL_CreateSurface(w, h, SDL_PIXELFORMAT_ARGB8888);
1446 if (!surface) {
1447 return NULL;
1448 }
1449 for (y = 0; y < h; ++y) {
1450 pixel = (Uint32 *)((Uint8 *)surface->pixels + y * surface->pitch);
1451 for (x = 0; x < w; ++x) {
1452 if ((x % 8) == 0) {
1453 datab = *data++;
1454 maskb = *mask++;
1455 }
1456 if (maskb & 0x80) {
1457 *pixel++ = (datab & 0x80) ? black : white;
1458 } else {
1459 *pixel++ = (datab & 0x80) ? inverted : transparent;
1460 }
1461 datab <<= 1;
1462 maskb <<= 1;
1463 }
1464 }
1465
1466 cursor = SDL_CreateColorCursor(surface, hot_x, hot_y);
1467
1468 SDL_DestroySurface(surface);
1469
1470 return cursor;
1471}
1472
1473SDL_Cursor *SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
1474{
1475 SDL_Mouse *mouse = SDL_GetMouse();
1476 SDL_Surface *temp = NULL;
1477 SDL_Cursor *cursor;
1478
1479 if (!surface) {
1480 SDL_InvalidParamError("surface");
1481 return NULL;
1482 }
1483
1484 // Allow specifying the hot spot via properties on the surface
1485 SDL_PropertiesID props = SDL_GetSurfaceProperties(surface);
1486 hot_x = (int)SDL_GetNumberProperty(props, SDL_PROP_SURFACE_HOTSPOT_X_NUMBER, hot_x);
1487 hot_y = (int)SDL_GetNumberProperty(props, SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER, hot_y);
1488
1489 // Sanity check the hot spot
1490 if ((hot_x < 0) || (hot_y < 0) ||
1491 (hot_x >= surface->w) || (hot_y >= surface->h)) {
1492 SDL_SetError("Cursor hot spot doesn't lie within cursor");
1493 return NULL;
1494 }
1495
1496 if (surface->format != SDL_PIXELFORMAT_ARGB8888) {
1497 temp = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888);
1498 if (!temp) {
1499 return NULL;
1500 }
1501 surface = temp;
1502 }
1503
1504 if (mouse->CreateCursor) {
1505 cursor = mouse->CreateCursor(surface, hot_x, hot_y);
1506 } else {
1507 cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor));
1508 }
1509 if (cursor) {
1510 cursor->next = mouse->cursors;
1511 mouse->cursors = cursor;
1512 }
1513
1514 SDL_DestroySurface(temp);
1515
1516 return cursor;
1517}
1518
1519SDL_Cursor *SDL_CreateSystemCursor(SDL_SystemCursor id)
1520{
1521 SDL_Mouse *mouse = SDL_GetMouse();
1522 SDL_Cursor *cursor;
1523
1524 if (!mouse->CreateSystemCursor) {
1525 SDL_SetError("CreateSystemCursor is not currently supported");
1526 return NULL;
1527 }
1528
1529 cursor = mouse->CreateSystemCursor(id);
1530 if (cursor) {
1531 cursor->next = mouse->cursors;
1532 mouse->cursors = cursor;
1533 }
1534
1535 return cursor;
1536}
1537
1538/* SDL_SetCursor(NULL) can be used to force the cursor redraw,
1539 if this is desired for any reason. This is used when setting
1540 the video mode and when the SDL window gains the mouse focus.
1541 */
1542bool SDL_SetCursor(SDL_Cursor *cursor)
1543{
1544 SDL_Mouse *mouse = SDL_GetMouse();
1545
1546 // Return immediately if setting the cursor to the currently set one (fixes #7151)
1547 if (cursor == mouse->cur_cursor) {
1548 return true;
1549 }
1550
1551 // Set the new cursor
1552 if (cursor) {
1553 // Make sure the cursor is still valid for this mouse
1554 if (cursor != mouse->def_cursor) {
1555 SDL_Cursor *found;
1556 for (found = mouse->cursors; found; found = found->next) {
1557 if (found == cursor) {
1558 break;
1559 }
1560 }
1561 if (!found) {
1562 return SDL_SetError("Cursor not associated with the current mouse");
1563 }
1564 }
1565 mouse->cur_cursor = cursor;
1566 } else {
1567 if (mouse->focus) {
1568 cursor = mouse->cur_cursor;
1569 } else {
1570 cursor = mouse->def_cursor;
1571 }
1572 }
1573
1574 if (cursor && (!mouse->focus || (mouse->cursor_shown && (!mouse->relative_mode || mouse->relative_mode_cursor_visible)))) {
1575 if (mouse->ShowCursor) {
1576 mouse->ShowCursor(cursor);
1577 }
1578 } else {
1579 if (mouse->ShowCursor) {
1580 mouse->ShowCursor(NULL);
1581 }
1582 }
1583 return true;
1584}
1585
1586SDL_Cursor *SDL_GetCursor(void)
1587{
1588 SDL_Mouse *mouse = SDL_GetMouse();
1589
1590 if (!mouse) {
1591 return NULL;
1592 }
1593 return mouse->cur_cursor;
1594}
1595
1596SDL_Cursor *SDL_GetDefaultCursor(void)
1597{
1598 SDL_Mouse *mouse = SDL_GetMouse();
1599
1600 if (!mouse) {
1601 return NULL;
1602 }
1603 return mouse->def_cursor;
1604}
1605
1606void SDL_DestroyCursor(SDL_Cursor *cursor)
1607{
1608 SDL_Mouse *mouse = SDL_GetMouse();
1609 SDL_Cursor *curr, *prev;
1610
1611 if (!cursor) {
1612 return;
1613 }
1614
1615 if (cursor == mouse->def_cursor) {
1616 return;
1617 }
1618 if (cursor == mouse->cur_cursor) {
1619 SDL_SetCursor(mouse->def_cursor);
1620 }
1621
1622 for (prev = NULL, curr = mouse->cursors; curr;
1623 prev = curr, curr = curr->next) {
1624 if (curr == cursor) {
1625 if (prev) {
1626 prev->next = curr->next;
1627 } else {
1628 mouse->cursors = curr->next;
1629 }
1630
1631 if (mouse->FreeCursor && curr->internal) {
1632 mouse->FreeCursor(curr);
1633 } else {
1634 SDL_free(curr);
1635 }
1636 return;
1637 }
1638 }
1639}
1640
1641bool SDL_ShowCursor(void)
1642{
1643 SDL_Mouse *mouse = SDL_GetMouse();
1644
1645 if (mouse->warp_emulation_active) {
1646 SDL_SetRelativeMouseMode(false);
1647 mouse->warp_emulation_active = false;
1648 }
1649
1650 if (!mouse->cursor_shown) {
1651 mouse->cursor_shown = true;
1652 SDL_SetCursor(NULL);
1653 }
1654 return true;
1655}
1656
1657bool SDL_HideCursor(void)
1658{
1659 SDL_Mouse *mouse = SDL_GetMouse();
1660
1661 if (mouse->cursor_shown) {
1662 mouse->cursor_shown = false;
1663 SDL_SetCursor(NULL);
1664 }
1665 return true;
1666}
1667
1668bool SDL_CursorVisible(void)
1669{
1670 SDL_Mouse *mouse = SDL_GetMouse();
1671
1672 return mouse->cursor_shown;
1673}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_mouse_c.h b/contrib/SDL-3.2.8/src/events/SDL_mouse_c.h
new file mode 100644
index 0000000..43cc520
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_mouse_c.h
@@ -0,0 +1,208 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_mouse_c_h_
24#define SDL_mouse_c_h_
25
26// Mouse events not associated with a specific input device
27#define SDL_GLOBAL_MOUSE_ID 0
28
29// The default mouse input device, for platforms that don't have multiple mice
30#define SDL_DEFAULT_MOUSE_ID 1
31
32typedef struct SDL_CursorData SDL_CursorData;
33
34struct SDL_Cursor
35{
36 struct SDL_Cursor *next;
37 SDL_CursorData *internal;
38};
39
40typedef struct
41{
42 Uint64 last_timestamp;
43 double click_motion_x;
44 double click_motion_y;
45 Uint8 click_count;
46} SDL_MouseClickState;
47
48typedef struct
49{
50 SDL_MouseID mouseID;
51 Uint32 buttonstate;
52
53 // Data for double-click tracking
54 int num_clickstates;
55 SDL_MouseClickState *clickstate;
56} SDL_MouseInputSource;
57
58typedef struct
59{
60 // Create a cursor from a surface
61 SDL_Cursor *(*CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y);
62
63 // Create a system cursor
64 SDL_Cursor *(*CreateSystemCursor)(SDL_SystemCursor id);
65
66 // Show the specified cursor, or hide if cursor is NULL
67 bool (*ShowCursor)(SDL_Cursor *cursor);
68
69 // This is called when a mouse motion event occurs
70 bool (*MoveCursor)(SDL_Cursor *cursor);
71
72 // Free a window manager cursor
73 void (*FreeCursor)(SDL_Cursor *cursor);
74
75 // Warp the mouse to (x,y) within a window
76 bool (*WarpMouse)(SDL_Window *window, float x, float y);
77
78 // Warp the mouse to (x,y) in screen space
79 bool (*WarpMouseGlobal)(float x, float y);
80
81 // Set relative mode
82 bool (*SetRelativeMouseMode)(bool enabled);
83
84 // Set mouse capture
85 bool (*CaptureMouse)(SDL_Window *window);
86
87 // Get absolute mouse coordinates. (x) and (y) are never NULL and set to zero before call.
88 SDL_MouseButtonFlags (*GetGlobalMouseState)(float *x, float *y);
89
90 // Platform-specific system mouse transform
91 void (*ApplySystemScale)(void *internal, Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float *x, float *y);
92 void *system_scale_data;
93
94 // Data common to all mice
95 SDL_Window *focus;
96 float x;
97 float y;
98 float x_accu;
99 float y_accu;
100 float last_x, last_y; // the last reported x and y coordinates
101 double click_motion_x;
102 double click_motion_y;
103 bool has_position;
104 bool relative_mode;
105 bool relative_mode_warp_motion;
106 bool relative_mode_cursor_visible;
107 bool relative_mode_center;
108 bool warp_emulation_hint;
109 bool warp_emulation_active;
110 bool warp_emulation_prohibited;
111 Uint64 last_center_warp_time_ns;
112 bool enable_normal_speed_scale;
113 float normal_speed_scale;
114 bool enable_relative_speed_scale;
115 float relative_speed_scale;
116 bool enable_relative_system_scale;
117 Uint32 double_click_time;
118 int double_click_radius;
119 bool touch_mouse_events;
120 bool mouse_touch_events;
121 bool pen_mouse_events;
122 bool pen_touch_events;
123 bool was_touch_mouse_events; // Was a touch-mouse event pending?
124 bool added_mouse_touch_device; // did we SDL_AddTouch() a virtual touch device for the mouse?
125 bool added_pen_touch_device; // did we SDL_AddTouch() a virtual touch device for pens?
126#ifdef SDL_PLATFORM_VITA
127 Uint8 vita_touch_mouse_device;
128#endif
129 bool auto_capture;
130 bool capture_desired;
131 SDL_Window *capture_window;
132
133 // Data for input source state
134 int num_sources;
135 SDL_MouseInputSource *sources;
136
137 SDL_Cursor *cursors;
138 SDL_Cursor *def_cursor;
139 SDL_Cursor *cur_cursor;
140 bool cursor_shown;
141
142 // Driver-dependent data.
143 void *internal;
144} SDL_Mouse;
145
146// Initialize the mouse subsystem, called before the main video driver is initialized
147extern bool SDL_PreInitMouse(void);
148
149// Finish initializing the mouse subsystem, called after the main video driver was initialized
150extern void SDL_PostInitMouse(void);
151
152// Return whether a device is actually a mouse
153extern bool SDL_IsMouse(Uint16 vendor, Uint16 product);
154
155// A mouse has been added to the system
156extern void SDL_AddMouse(SDL_MouseID mouseID, const char *name, bool send_event);
157
158// A mouse has been removed from the system
159extern void SDL_RemoveMouse(SDL_MouseID mouseID, bool send_event);
160
161// Get the mouse state structure
162extern SDL_Mouse *SDL_GetMouse(void);
163
164// Set the default mouse cursor
165extern void SDL_SetDefaultCursor(SDL_Cursor *cursor);
166
167// Get the preferred default system cursor
168extern SDL_SystemCursor SDL_GetDefaultSystemCursor(void);
169
170// Set the mouse focus window
171extern void SDL_SetMouseFocus(SDL_Window *window);
172
173// Update the mouse capture window
174extern bool SDL_UpdateMouseCapture(bool force_release);
175
176// Send a mouse motion event
177extern void SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, bool relative, float x, float y);
178
179// Send a mouse button event
180extern void SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down);
181
182// Send a mouse button event with a click count
183extern void SDL_SendMouseButtonClicks(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down, int clicks);
184
185// Send a mouse wheel event
186extern void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction);
187
188// Warp the mouse within the window, potentially overriding relative mode
189extern void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, bool ignore_relative_mode);
190
191// Relative mouse mode
192extern bool SDL_SetRelativeMouseMode(bool enabled);
193extern bool SDL_GetRelativeMouseMode(void);
194extern void SDL_UpdateRelativeMouseMode(void);
195extern void SDL_DisableMouseWarpEmulation(void);
196
197// TODO RECONNECT: Set mouse state to "zero"
198#if 0
199extern void SDL_ResetMouse(void);
200#endif // 0
201
202// Check if mouse position is within window or captured by window
203extern bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y);
204
205// Shutdown the mouse subsystem
206extern void SDL_QuitMouse(void);
207
208#endif // SDL_mouse_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_pen.c b/contrib/SDL-3.2.8/src/events/SDL_pen.c
new file mode 100644
index 0000000..1ef7062
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_pen.c
@@ -0,0 +1,577 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// Pressure-sensitive pen handling code for SDL
24
25#include "../SDL_hints_c.h"
26#include "SDL_events_c.h"
27#include "SDL_pen_c.h"
28
29static SDL_PenID pen_touching = 0; // used for synthetic mouse/touch events.
30
31typedef struct SDL_Pen
32{
33 SDL_PenID instance_id;
34 char *name;
35 SDL_PenInfo info;
36 float axes[SDL_PEN_AXIS_COUNT];
37 float x;
38 float y;
39 SDL_PenInputFlags input_state;
40 void *driverdata;
41} SDL_Pen;
42
43// we assume there's usually 0-1 pens in most cases and this list doesn't
44// usually change after startup, so a simple array with a RWlock is fine for now.
45static SDL_RWLock *pen_device_rwlock = NULL;
46static SDL_Pen *pen_devices SDL_GUARDED_BY(pen_device_rwlock) = NULL;
47static int pen_device_count SDL_GUARDED_BY(pen_device_rwlock) = 0;
48
49// You must hold pen_device_rwlock before calling this, and result is only safe while lock is held!
50// If SDL isn't initialized, grabbing the NULL lock is a no-op and there will be zero devices, so
51// locking and calling this in that case will do the right thing.
52static SDL_Pen *FindPenByInstanceId(SDL_PenID instance_id) SDL_REQUIRES_SHARED(pen_device_rwlock)
53{
54 if (instance_id) {
55 for (int i = 0; i < pen_device_count; i++) {
56 if (pen_devices[i].instance_id == instance_id) {
57 return &pen_devices[i];
58 }
59 }
60 }
61 SDL_SetError("Invalid pen instance ID");
62 return NULL;
63}
64
65SDL_PenID SDL_FindPenByHandle(void *handle)
66{
67 SDL_PenID result = 0;
68 SDL_LockRWLockForReading(pen_device_rwlock);
69 for (int i = 0; i < pen_device_count; i++) {
70 if (pen_devices[i].driverdata == handle) {
71 result = pen_devices[i].instance_id;
72 break;
73 }
74 }
75 SDL_UnlockRWLock(pen_device_rwlock);
76 return result;
77}
78
79SDL_PenID SDL_FindPenByCallback(bool (*callback)(void *handle, void *userdata), void *userdata)
80{
81 SDL_PenID result = 0;
82 SDL_LockRWLockForReading(pen_device_rwlock);
83 for (int i = 0; i < pen_device_count; i++) {
84 if (callback(pen_devices[i].driverdata, userdata)) {
85 result = pen_devices[i].instance_id;
86 break;
87 }
88 }
89 SDL_UnlockRWLock(pen_device_rwlock);
90 return result;
91}
92
93
94
95// public API ...
96
97bool SDL_InitPen(void)
98{
99 SDL_assert(pen_device_rwlock == NULL);
100 SDL_assert(pen_devices == NULL);
101 SDL_assert(pen_device_count == 0);
102 pen_device_rwlock = SDL_CreateRWLock();
103 if (!pen_device_rwlock) {
104 return false;
105 }
106 return true;
107}
108
109void SDL_QuitPen(void)
110{
111 SDL_DestroyRWLock(pen_device_rwlock);
112 pen_device_rwlock = NULL;
113 if (pen_devices) {
114 for (int i = pen_device_count; i--; ) {
115 SDL_free(pen_devices[i].name);
116 }
117 SDL_free(pen_devices);
118 pen_devices = NULL;
119 }
120 pen_device_count = 0;
121 pen_touching = 0;
122}
123
124#if 0 // not a public API at the moment.
125SDL_PenID *SDL_GetPens(int *count)
126{
127 SDL_LockRWLockForReading(pen_device_rwlock);
128 const int num_devices = pen_device_count;
129 SDL_PenID *result = (SDL_PenID *) SDL_malloc((num_devices + 1) * sizeof (SDL_PenID));
130 if (result) {
131 for (int i = 0; i < num_devices; i++) {
132 result[i] = pen_devices[i].instance_id;
133 }
134 result[num_devices] = 0; // null-terminated.
135 }
136 SDL_UnlockRWLock(pen_device_rwlock);
137
138 if (count) {
139 *count = result ? num_devices : 0;
140 }
141 return result;
142}
143
144const char *SDL_GetPenName(SDL_PenID instance_id)
145{
146 SDL_LockRWLockForReading(pen_device_rwlock);
147 const SDL_Pen *pen = FindPenByInstanceId(instance_id);
148 const char *result = pen ? SDL_GetPersistentString(pen->name) : NULL;
149 SDL_UnlockRWLock(pen_device_rwlock);
150 return result;
151}
152
153bool SDL_GetPenInfo(SDL_PenID instance_id, SDL_PenInfo *info)
154{
155 SDL_LockRWLockForReading(pen_device_rwlock);
156 const SDL_Pen *pen = FindPenByInstanceId(instance_id);
157 const bool result = pen ? true : false;
158 if (info) {
159 if (result) {
160 SDL_copyp(info, &pen->info);
161 } else {
162 SDL_zerop(info);
163 }
164 }
165 SDL_UnlockRWLock(pen_device_rwlock);
166 return result;
167}
168
169bool SDL_PenConnected(SDL_PenID instance_id)
170{
171 SDL_LockRWLockForReading(pen_device_rwlock);
172 const SDL_Pen *pen = FindPenByInstanceId(instance_id);
173 const bool result = (pen != NULL);
174 SDL_UnlockRWLock(pen_device_rwlock);
175 return result;
176}
177#endif
178
179SDL_PenInputFlags SDL_GetPenStatus(SDL_PenID instance_id, float *axes, int num_axes)
180{
181 if (num_axes < 0) {
182 num_axes = 0;
183 }
184
185 SDL_LockRWLockForReading(pen_device_rwlock);
186 const SDL_Pen *pen = FindPenByInstanceId(instance_id);
187 SDL_PenInputFlags result = 0;
188 if (pen) {
189 result = pen->input_state;
190 if (axes && num_axes) {
191 SDL_memcpy(axes, pen->axes, SDL_min(num_axes, SDL_PEN_AXIS_COUNT) * sizeof (*axes));
192 // zero out axes we don't know about, in case the caller built with newer SDL headers that support more of them.
193 if (num_axes > SDL_PEN_AXIS_COUNT) {
194 SDL_memset(&axes[SDL_PEN_AXIS_COUNT], '\0', (num_axes - SDL_PEN_AXIS_COUNT) * sizeof (*axes));
195 }
196 }
197 }
198 SDL_UnlockRWLock(pen_device_rwlock);
199 return result;
200}
201
202SDL_PenCapabilityFlags SDL_GetPenCapabilityFromAxis(SDL_PenAxis axis)
203{
204 // the initial capability bits happen to match up, but as
205 // more features show up later, the bits may no longer be contiguous!
206 if ((axis >= SDL_PEN_AXIS_PRESSURE) && (axis <= SDL_PEN_AXIS_SLIDER)) {
207 return ((SDL_PenCapabilityFlags) 1u) << ((SDL_PenCapabilityFlags) axis);
208 }
209 return 0; // oh well.
210}
211
212SDL_PenID SDL_AddPenDevice(Uint64 timestamp, const char *name, const SDL_PenInfo *info, void *handle)
213{
214 SDL_assert(handle != NULL); // just allocate a Uint8 so you have a unique pointer if not needed!
215 SDL_assert(SDL_FindPenByHandle(handle) == 0); // Backends shouldn't double-add pens!
216 SDL_assert(pen_device_rwlock != NULL); // subsystem should be initialized by now!
217
218 char *namecpy = SDL_strdup(name ? name : "Unnamed pen");
219 if (!namecpy) {
220 return 0;
221 }
222
223 SDL_PenID result = 0;
224
225 SDL_LockRWLockForWriting(pen_device_rwlock);
226
227 SDL_Pen *pen = NULL;
228 void *ptr = SDL_realloc(pen_devices, (pen_device_count + 1) * sizeof (*pen));
229 if (ptr) {
230 result = (SDL_PenID) SDL_GetNextObjectID();
231 pen_devices = (SDL_Pen *) ptr;
232 pen = &pen_devices[pen_device_count];
233 pen_device_count++;
234
235 SDL_zerop(pen);
236 pen->instance_id = result;
237 pen->name = namecpy;
238 if (info) {
239 SDL_copyp(&pen->info, info);
240 }
241 pen->driverdata = handle;
242 // axes and input state defaults to zero.
243 }
244 SDL_UnlockRWLock(pen_device_rwlock);
245
246 if (!pen) {
247 SDL_free(namecpy);
248 }
249
250 if (result && SDL_EventEnabled(SDL_EVENT_PEN_PROXIMITY_IN)) {
251 SDL_Event event;
252 SDL_zero(event);
253 event.pproximity.type = SDL_EVENT_PEN_PROXIMITY_IN;
254 event.pproximity.timestamp = timestamp;
255 event.pproximity.which = result;
256 SDL_PushEvent(&event);
257 }
258
259 return result;
260}
261
262void SDL_RemovePenDevice(Uint64 timestamp, SDL_PenID instance_id)
263{
264 if (!instance_id) {
265 return;
266 }
267
268 SDL_LockRWLockForWriting(pen_device_rwlock);
269 SDL_Pen *pen = FindPenByInstanceId(instance_id);
270 if (pen) {
271 SDL_free(pen->name);
272 // we don't free `pen`, it's just part of simple array. Shuffle it out.
273 const int idx = ((int) (pen - pen_devices));
274 SDL_assert((idx >= 0) && (idx < pen_device_count));
275 if ( idx < (pen_device_count - 1) ) {
276 SDL_memmove(&pen_devices[idx], &pen_devices[idx + 1], sizeof (*pen) * ((pen_device_count - idx) - 1));
277 }
278
279 SDL_assert(pen_device_count > 0);
280 pen_device_count--;
281
282 if (pen_device_count) {
283 void *ptr = SDL_realloc(pen_devices, sizeof (*pen) * pen_device_count); // shrink it down.
284 if (ptr) {
285 pen_devices = (SDL_Pen *) ptr;
286 }
287 } else {
288 SDL_free(pen_devices);
289 pen_devices = NULL;
290 }
291 }
292 SDL_UnlockRWLock(pen_device_rwlock);
293
294 if (pen && SDL_EventEnabled(SDL_EVENT_PEN_PROXIMITY_OUT)) {
295 SDL_Event event;
296 SDL_zero(event);
297 event.pproximity.type = SDL_EVENT_PEN_PROXIMITY_OUT;
298 event.pproximity.timestamp = timestamp;
299 event.pproximity.which = instance_id;
300 SDL_PushEvent(&event);
301 }
302}
303
304// This presumably is happening during video quit, so we don't send PROXIMITY_OUT events here.
305void SDL_RemoveAllPenDevices(void (*callback)(SDL_PenID instance_id, void *handle, void *userdata), void *userdata)
306{
307 SDL_LockRWLockForWriting(pen_device_rwlock);
308 if (pen_device_count > 0) {
309 SDL_assert(pen_devices != NULL);
310 for (int i = 0; i < pen_device_count; i++) {
311 callback(pen_devices[i].instance_id, pen_devices[i].driverdata, userdata);
312 SDL_free(pen_devices[i].name);
313 }
314 }
315 SDL_free(pen_devices);
316 pen_devices = NULL;
317 SDL_UnlockRWLock(pen_device_rwlock);
318}
319
320void SDL_SendPenTouch(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, bool eraser, bool down)
321{
322 bool send_event = false;
323 SDL_PenInputFlags input_state = 0;
324 float x = 0.0f;
325 float y = 0.0f;
326
327 // note that this locks for _reading_ because the lock protects the
328 // pen_devices array from being reallocated from under us, not the data in it;
329 // we assume only one thread (in the backend) is modifying an individual pen at
330 // a time, so it can update input state cleanly here.
331 SDL_LockRWLockForReading(pen_device_rwlock);
332 SDL_Pen *pen = FindPenByInstanceId(instance_id);
333 if (pen) {
334 input_state = pen->input_state;
335 x = pen->x;
336 y = pen->y;
337
338 if (down && ((input_state & SDL_PEN_INPUT_DOWN) == 0)) {
339 input_state |= SDL_PEN_INPUT_DOWN;
340 send_event = true;
341 } else if (!down && (input_state & SDL_PEN_INPUT_DOWN)) {
342 input_state &= ~SDL_PEN_INPUT_DOWN;
343 send_event = true;
344 }
345
346 if (eraser && ((input_state & SDL_PEN_INPUT_ERASER_TIP) == 0)) {
347 input_state |= SDL_PEN_INPUT_ERASER_TIP;
348 send_event = true;
349 } else if (!eraser && (input_state & SDL_PEN_INPUT_ERASER_TIP)) {
350 input_state &= ~SDL_PEN_INPUT_ERASER_TIP;
351 send_event = true;
352 }
353
354 pen->input_state = input_state; // we could do an SDL_SetAtomicInt here if we run into trouble...
355 }
356 SDL_UnlockRWLock(pen_device_rwlock);
357
358 if (send_event) {
359 const SDL_EventType evtype = down ? SDL_EVENT_PEN_DOWN : SDL_EVENT_PEN_UP;
360 if (SDL_EventEnabled(evtype)) {
361 SDL_Event event;
362 SDL_zero(event);
363 event.ptouch.type = evtype;
364 event.ptouch.timestamp = timestamp;
365 event.ptouch.windowID = window ? window->id : 0;
366 event.ptouch.which = instance_id;
367 event.ptouch.pen_state = input_state;
368 event.ptouch.x = x;
369 event.ptouch.y = y;
370 event.ptouch.eraser = eraser;
371 event.ptouch.down = down;
372 SDL_PushEvent(&event);
373 }
374
375 SDL_Mouse *mouse = SDL_GetMouse();
376 if (mouse && window) {
377 if (mouse->pen_mouse_events) {
378 if (down) {
379 if (!pen_touching) {
380 SDL_SendMouseMotion(timestamp, window, SDL_PEN_MOUSEID, false, x, y);
381 SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, SDL_BUTTON_LEFT, true);
382 }
383 } else {
384 if (pen_touching == instance_id) {
385 SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, SDL_BUTTON_LEFT, false);
386 }
387 }
388 }
389
390 if (mouse->pen_touch_events) {
391 const SDL_EventType touchtype = down ? SDL_EVENT_FINGER_DOWN : SDL_EVENT_FINGER_UP;
392 const float normalized_x = x / (float)window->w;
393 const float normalized_y = y / (float)window->h;
394 if (!pen_touching || (pen_touching == instance_id)) {
395 SDL_SendTouch(timestamp, SDL_PEN_TOUCHID, SDL_BUTTON_LEFT, window, touchtype, normalized_x, normalized_y, pen->axes[SDL_PEN_AXIS_PRESSURE]);
396 }
397 }
398 }
399
400 if (down) {
401 if (!pen_touching) {
402 pen_touching = instance_id;
403 }
404 } else {
405 if (pen_touching == instance_id) {
406 pen_touching = 0;
407 }
408 }
409 }
410}
411
412void SDL_SendPenAxis(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, SDL_PenAxis axis, float value)
413{
414 SDL_assert((axis >= 0) && (axis < SDL_PEN_AXIS_COUNT)); // fix the backend if this triggers.
415
416 bool send_event = false;
417 SDL_PenInputFlags input_state = 0;
418 float x = 0.0f;
419 float y = 0.0f;
420
421 // note that this locks for _reading_ because the lock protects the
422 // pen_devices array from being reallocated from under us, not the data in it;
423 // we assume only one thread (in the backend) is modifying an individual pen at
424 // a time, so it can update input state cleanly here.
425 SDL_LockRWLockForReading(pen_device_rwlock);
426 SDL_Pen *pen = FindPenByInstanceId(instance_id);
427 if (pen) {
428 if (pen->axes[axis] != value) {
429 pen->axes[axis] = value; // we could do an SDL_SetAtomicInt here if we run into trouble...
430 input_state = pen->input_state;
431 x = pen->x;
432 y = pen->y;
433 send_event = true;
434 }
435 }
436 SDL_UnlockRWLock(pen_device_rwlock);
437
438 if (send_event && SDL_EventEnabled(SDL_EVENT_PEN_AXIS)) {
439 SDL_Event event;
440 SDL_zero(event);
441 event.paxis.type = SDL_EVENT_PEN_AXIS;
442 event.paxis.timestamp = timestamp;
443 event.paxis.windowID = window ? window->id : 0;
444 event.paxis.which = instance_id;
445 event.paxis.pen_state = input_state;
446 event.paxis.x = x;
447 event.paxis.y = y;
448 event.paxis.axis = axis;
449 event.paxis.value = value;
450 SDL_PushEvent(&event);
451
452 if (window && (axis == SDL_PEN_AXIS_PRESSURE) && (pen_touching == instance_id)) {
453 SDL_Mouse *mouse = SDL_GetMouse();
454 if (mouse && mouse->pen_touch_events) {
455 const float normalized_x = x / (float)window->w;
456 const float normalized_y = y / (float)window->h;
457 SDL_SendTouchMotion(timestamp, SDL_PEN_TOUCHID, SDL_BUTTON_LEFT, window, normalized_x, normalized_y, value);
458 }
459 }
460 }
461}
462
463void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, float x, float y)
464{
465 bool send_event = false;
466 SDL_PenInputFlags input_state = 0;
467
468 // note that this locks for _reading_ because the lock protects the
469 // pen_devices array from being reallocated from under us, not the data in it;
470 // we assume only one thread (in the backend) is modifying an individual pen at
471 // a time, so it can update input state cleanly here.
472 SDL_LockRWLockForReading(pen_device_rwlock);
473 SDL_Pen *pen = FindPenByInstanceId(instance_id);
474 if (pen) {
475 if ((pen->x != x) || (pen->y != y)) {
476 pen->x = x; // we could do an SDL_SetAtomicInt here if we run into trouble...
477 pen->y = y; // we could do an SDL_SetAtomicInt here if we run into trouble...
478 input_state = pen->input_state;
479 send_event = true;
480 }
481 }
482 SDL_UnlockRWLock(pen_device_rwlock);
483
484 if (send_event && SDL_EventEnabled(SDL_EVENT_PEN_MOTION)) {
485 SDL_Event event;
486 SDL_zero(event);
487 event.pmotion.type = SDL_EVENT_PEN_MOTION;
488 event.pmotion.timestamp = timestamp;
489 event.pmotion.windowID = window ? window->id : 0;
490 event.pmotion.which = instance_id;
491 event.pmotion.pen_state = input_state;
492 event.pmotion.x = x;
493 event.pmotion.y = y;
494 SDL_PushEvent(&event);
495
496 if (window) {
497 SDL_Mouse *mouse = SDL_GetMouse();
498 if (mouse) {
499 if (pen_touching == instance_id) {
500 if (mouse->pen_mouse_events) {
501 SDL_SendMouseMotion(timestamp, window, SDL_PEN_MOUSEID, false, x, y);
502 }
503
504 if (mouse->pen_touch_events) {
505 const float normalized_x = x / (float)window->w;
506 const float normalized_y = y / (float)window->h;
507 SDL_SendTouchMotion(timestamp, SDL_PEN_TOUCHID, SDL_BUTTON_LEFT, window, normalized_x, normalized_y, pen->axes[SDL_PEN_AXIS_PRESSURE]);
508 }
509 } else if (pen_touching == 0) { // send mouse motion (without a pressed button) for pens that aren't touching.
510 // this might cause a little chaos if you have multiple pens hovering at the same time, but this seems unlikely in the real world, and also something you did to yourself. :)
511 SDL_SendMouseMotion(timestamp, window, SDL_PEN_MOUSEID, false, x, y);
512 }
513 }
514 }
515 }
516}
517
518void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, Uint8 button, bool down)
519{
520 bool send_event = false;
521 SDL_PenInputFlags input_state = 0;
522 float x = 0.0f;
523 float y = 0.0f;
524
525 if ((button < 1) || (button > 5)) {
526 return; // clamp for now.
527 }
528
529 // note that this locks for _reading_ because the lock protects the
530 // pen_devices array from being reallocated from under us, not the data in it;
531 // we assume only one thread (in the backend) is modifying an individual pen at
532 // a time, so it can update input state cleanly here.
533 SDL_LockRWLockForReading(pen_device_rwlock);
534 SDL_Pen *pen = FindPenByInstanceId(instance_id);
535 if (pen) {
536 input_state = pen->input_state;
537 const Uint32 flag = (Uint32) (1u << button);
538 const bool current = ((input_state & flag) != 0);
539 x = pen->x;
540 y = pen->y;
541 if (down && !current) {
542 input_state |= flag;
543 send_event = true;
544 } else if (!down && current) {
545 input_state &= ~flag;
546 send_event = true;
547 }
548 pen->input_state = input_state; // we could do an SDL_SetAtomicInt here if we run into trouble...
549 }
550 SDL_UnlockRWLock(pen_device_rwlock);
551
552 if (send_event) {
553 const SDL_EventType evtype = down ? SDL_EVENT_PEN_BUTTON_DOWN : SDL_EVENT_PEN_BUTTON_UP;
554 if (SDL_EventEnabled(evtype)) {
555 SDL_Event event;
556 SDL_zero(event);
557 event.pbutton.type = evtype;
558 event.pbutton.timestamp = timestamp;
559 event.pbutton.windowID = window ? window->id : 0;
560 event.pbutton.which = instance_id;
561 event.pbutton.pen_state = input_state;
562 event.pbutton.x = x;
563 event.pbutton.y = y;
564 event.pbutton.button = button;
565 event.pbutton.down = down;
566 SDL_PushEvent(&event);
567
568 if (window && (pen_touching == instance_id)) {
569 SDL_Mouse *mouse = SDL_GetMouse();
570 if (mouse && mouse->pen_mouse_events) {
571 SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, button + 1, down);
572 }
573 }
574 }
575 }
576}
577
diff --git a/contrib/SDL-3.2.8/src/events/SDL_pen_c.h b/contrib/SDL-3.2.8/src/events/SDL_pen_c.h
new file mode 100644
index 0000000..1eff47f
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_pen_c.h
@@ -0,0 +1,99 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#include "../SDL_internal.h"
23
24#ifndef SDL_pen_c_h_
25#define SDL_pen_c_h_
26
27#include "SDL_mouse_c.h"
28
29typedef Uint32 SDL_PenCapabilityFlags;
30#define SDL_PEN_CAPABILITY_PRESSURE (1u << 0) /**< Provides pressure information on SDL_PEN_AXIS_PRESSURE. */
31#define SDL_PEN_CAPABILITY_XTILT (1u << 1) /**< Provides horizontal tilt information on SDL_PEN_AXIS_XTILT. */
32#define SDL_PEN_CAPABILITY_YTILT (1u << 2) /**< Provides vertical tilt information on SDL_PEN_AXIS_YTILT. */
33#define SDL_PEN_CAPABILITY_DISTANCE (1u << 3) /**< Provides distance to drawing tablet on SDL_PEN_AXIS_DISTANCE. */
34#define SDL_PEN_CAPABILITY_ROTATION (1u << 4) /**< Provides barrel rotation info on SDL_PEN_AXIS_ROTATION. */
35#define SDL_PEN_CAPABILITY_SLIDER (1u << 5) /**< Provides slider/finger wheel/etc on SDL_PEN_AXIS_SLIDER. */
36#define SDL_PEN_CAPABILITY_TANGENTIAL_PRESSURE (1u << 6) /**< Provides barrel pressure on SDL_PEN_AXIS_TANGENTIAL_PRESSURE. */
37#define SDL_PEN_CAPABILITY_ERASER (1u << 7) /**< Pen also has an eraser tip. */
38
39typedef enum SDL_PenSubtype
40{
41 SDL_PEN_TYPE_UNKNOWN, /**< Unknown pen device */
42 SDL_PEN_TYPE_ERASER, /**< Eraser */
43 SDL_PEN_TYPE_PEN, /**< Generic pen; this is the default. */
44 SDL_PEN_TYPE_PENCIL, /**< Pencil */
45 SDL_PEN_TYPE_BRUSH, /**< Brush-like device */
46 SDL_PEN_TYPE_AIRBRUSH /**< Airbrush device that "sprays" ink */
47} SDL_PenSubtype;
48
49typedef struct SDL_PenInfo
50{
51 SDL_PenCapabilityFlags capabilities; /**< bitflags of device capabilities */
52 float max_tilt; /**< Physical maximum tilt angle, for XTILT and YTILT, or -1.0f if unknown. Pens cannot typically tilt all the way to 90 degrees, so this value is usually less than 90.0. */
53 Uint32 wacom_id; /**< For Wacom devices: wacom tool type ID, otherwise 0 (useful e.g. with libwacom) */
54 int num_buttons; /**< Number of pen buttons (not counting the pen tip), or -1 if unknown. */
55 SDL_PenSubtype subtype; /**< type of pen device */
56} SDL_PenInfo;
57
58// Backend calls this when a new pen device is hotplugged, plus once for each pen already connected at startup.
59// Note that name and info are copied but currently unused; this is placeholder for a potentially more robust API later.
60// Both are allowed to be NULL.
61extern SDL_PenID SDL_AddPenDevice(Uint64 timestamp, const char *name, const SDL_PenInfo *info, void *handle);
62
63// Backend calls this when an existing pen device is disconnected during runtime. They must free their own stuff separately.
64extern void SDL_RemovePenDevice(Uint64 timestamp, SDL_PenID instance_id);
65
66// Backend can call this to remove all pens, probably during shutdown, with a callback to let them free their own handle.
67extern void SDL_RemoveAllPenDevices(void (*callback)(SDL_PenID instance_id, void *handle, void *userdata), void *userdata);
68
69// Backend calls this when a pen's button changes, to generate events and update state.
70extern void SDL_SendPenTouch(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, bool eraser, bool down);
71
72// Backend calls this when a pen moves on the tablet, to generate events and update state.
73extern void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, float x, float y);
74
75// Backend calls this when a pen's axis changes, to generate events and update state.
76extern void SDL_SendPenAxis(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, SDL_PenAxis axis, float value);
77
78// Backend calls this when a pen's button changes, to generate events and update state.
79extern void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, Uint8 button, bool down);
80
81// Backend can optionally use this to find the SDL_PenID for the `handle` that was passed to SDL_AddPenDevice.
82extern SDL_PenID SDL_FindPenByHandle(void *handle);
83
84// Backend can optionally use this to find a SDL_PenID, selected by a callback examining all devices. Zero if not found.
85extern SDL_PenID SDL_FindPenByCallback(bool (*callback)(void *handle, void *userdata), void *userdata);
86
87// Backend can use this to query current pen status.
88SDL_PenInputFlags SDL_GetPenStatus(SDL_PenID instance_id, float *axes, int num_axes);
89
90// Backend can use this to map an axis to a capability bit.
91SDL_PenCapabilityFlags SDL_GetPenCapabilityFromAxis(SDL_PenAxis axis);
92
93// Higher-level SDL video subsystem code calls this when starting up. Backends shouldn't.
94extern bool SDL_InitPen(void);
95
96// Higher-level SDL video subsystem code calls this when shutting down. Backends shouldn't.
97extern void SDL_QuitPen(void);
98
99#endif // SDL_pen_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_quit.c b/contrib/SDL-3.2.8/src/events/SDL_quit.c
new file mode 100644
index 0000000..5456203
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_quit.c
@@ -0,0 +1,194 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// General quit handling code for SDL
24
25#ifdef HAVE_SIGNAL_H
26#include <signal.h>
27#endif
28
29#include "SDL_events_c.h"
30
31#if defined(HAVE_SIGNAL_H) || defined(HAVE_SIGACTION)
32#define HAVE_SIGNAL_SUPPORT 1
33#endif
34
35#ifdef HAVE_SIGNAL_SUPPORT
36static bool disable_signals = false;
37static bool send_quit_pending = false;
38
39#ifdef SDL_BACKGROUNDING_SIGNAL
40static bool send_backgrounding_pending = false;
41#endif
42
43#ifdef SDL_FOREGROUNDING_SIGNAL
44static bool send_foregrounding_pending = false;
45#endif
46
47static void SDL_HandleSIG(int sig)
48{
49 // Reset the signal handler
50 (void)signal(sig, SDL_HandleSIG);
51
52 // Send a quit event next time the event loop pumps.
53 // We can't send it in signal handler; SDL_malloc() might be interrupted!
54 if ((sig == SIGINT) || (sig == SIGTERM)) {
55 send_quit_pending = true;
56 }
57
58#ifdef SDL_BACKGROUNDING_SIGNAL
59 else if (sig == SDL_BACKGROUNDING_SIGNAL) {
60 send_backgrounding_pending = true;
61 }
62#endif
63
64#ifdef SDL_FOREGROUNDING_SIGNAL
65 else if (sig == SDL_FOREGROUNDING_SIGNAL) {
66 send_foregrounding_pending = true;
67 }
68#endif
69}
70
71static void SDL_EventSignal_Init(const int sig)
72{
73#ifdef HAVE_SIGACTION
74 struct sigaction action;
75
76 sigaction(sig, NULL, &action);
77#ifdef HAVE_SA_SIGACTION
78 if (action.sa_handler == SIG_DFL && (void (*)(int))action.sa_sigaction == SIG_DFL) {
79#else
80 if (action.sa_handler == SIG_DFL) {
81#endif
82 action.sa_handler = SDL_HandleSIG;
83 sigaction(sig, &action, NULL);
84 }
85#elif defined(HAVE_SIGNAL_H)
86 void (*ohandler)(int) = signal(sig, SDL_HandleSIG);
87 if (ohandler != SIG_DFL) {
88 signal(sig, ohandler);
89 }
90#endif
91}
92
93static void SDL_EventSignal_Quit(const int sig)
94{
95#ifdef HAVE_SIGACTION
96 struct sigaction action;
97 sigaction(sig, NULL, &action);
98 if (action.sa_handler == SDL_HandleSIG) {
99 action.sa_handler = SIG_DFL;
100 sigaction(sig, &action, NULL);
101 }
102#elif defined(HAVE_SIGNAL_H)
103 void (*ohandler)(int) = signal(sig, SIG_DFL);
104 if (ohandler != SDL_HandleSIG) {
105 signal(sig, ohandler);
106 }
107#endif // HAVE_SIGNAL_H
108}
109
110// Public functions
111static bool SDL_QuitInit_Internal(void)
112{
113 // Both SIGINT and SIGTERM are translated into quit interrupts
114 // and SDL can be built to simulate iOS/Android semantics with arbitrary signals.
115 SDL_EventSignal_Init(SIGINT);
116 SDL_EventSignal_Init(SIGTERM);
117
118#ifdef SDL_BACKGROUNDING_SIGNAL
119 SDL_EventSignal_Init(SDL_BACKGROUNDING_SIGNAL);
120#endif
121
122#ifdef SDL_FOREGROUNDING_SIGNAL
123 SDL_EventSignal_Init(SDL_FOREGROUNDING_SIGNAL);
124#endif
125
126 // That's it!
127 return true;
128}
129
130static void SDL_QuitQuit_Internal(void)
131{
132 SDL_EventSignal_Quit(SIGINT);
133 SDL_EventSignal_Quit(SIGTERM);
134
135#ifdef SDL_BACKGROUNDING_SIGNAL
136 SDL_EventSignal_Quit(SDL_BACKGROUNDING_SIGNAL);
137#endif
138
139#ifdef SDL_FOREGROUNDING_SIGNAL
140 SDL_EventSignal_Quit(SDL_FOREGROUNDING_SIGNAL);
141#endif
142}
143#endif
144
145bool SDL_InitQuit(void)
146{
147#ifdef HAVE_SIGNAL_SUPPORT
148 if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) {
149 return SDL_QuitInit_Internal();
150 }
151#endif
152 return true;
153}
154
155void SDL_QuitQuit(void)
156{
157#ifdef HAVE_SIGNAL_SUPPORT
158 if (!disable_signals) {
159 SDL_QuitQuit_Internal();
160 }
161#endif
162}
163
164void SDL_SendPendingSignalEvents(void)
165{
166#ifdef HAVE_SIGNAL_SUPPORT
167 if (send_quit_pending) {
168 SDL_SendQuit();
169 SDL_assert(!send_quit_pending);
170 }
171
172#ifdef SDL_BACKGROUNDING_SIGNAL
173 if (send_backgrounding_pending) {
174 send_backgrounding_pending = false;
175 SDL_OnApplicationWillEnterBackground();
176 }
177#endif
178
179#ifdef SDL_FOREGROUNDING_SIGNAL
180 if (send_foregrounding_pending) {
181 send_foregrounding_pending = false;
182 SDL_OnApplicationDidEnterForeground();
183 }
184#endif
185#endif
186}
187
188void SDL_SendQuit(void)
189{
190#ifdef HAVE_SIGNAL_SUPPORT
191 send_quit_pending = false;
192#endif
193 SDL_SendAppEvent(SDL_EVENT_QUIT);
194}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_scancode_tables.c b/contrib/SDL-3.2.8/src/events/SDL_scancode_tables.c
new file mode 100644
index 0000000..a780f13
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_scancode_tables.c
@@ -0,0 +1,71 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#if defined(SDL_INPUT_LINUXEV) || defined(SDL_VIDEO_DRIVER_WAYLAND) || defined(SDL_VIDEO_DRIVER_X11)
24
25#include "SDL_scancode_tables_c.h"
26
27#include "scancodes_darwin.h"
28#include "scancodes_linux.h"
29#include "scancodes_xfree86.h"
30
31static const struct
32{
33 SDL_ScancodeTable table;
34 SDL_Scancode const *scancodes;
35 int num_entries;
36} SDL_scancode_tables[] = {
37 { SDL_SCANCODE_TABLE_DARWIN, darwin_scancode_table, SDL_arraysize(darwin_scancode_table) },
38 { SDL_SCANCODE_TABLE_LINUX, linux_scancode_table, SDL_arraysize(linux_scancode_table) },
39 { SDL_SCANCODE_TABLE_XFREE86_1, xfree86_scancode_table, SDL_arraysize(xfree86_scancode_table) },
40 { SDL_SCANCODE_TABLE_XFREE86_2, xfree86_scancode_table2, SDL_arraysize(xfree86_scancode_table2) },
41 { SDL_SCANCODE_TABLE_XVNC, xvnc_scancode_table, SDL_arraysize(xvnc_scancode_table) },
42};
43
44const SDL_Scancode *SDL_GetScancodeTable(SDL_ScancodeTable table, int *num_entries)
45{
46 int i;
47
48 for (i = 0; i < SDL_arraysize(SDL_scancode_tables); ++i) {
49 if (table == SDL_scancode_tables[i].table) {
50 *num_entries = SDL_scancode_tables[i].num_entries;
51 return SDL_scancode_tables[i].scancodes;
52 }
53 }
54
55 *num_entries = 0;
56 return NULL;
57}
58
59SDL_Scancode SDL_GetScancodeFromTable(SDL_ScancodeTable table, int keycode)
60{
61 SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
62 int num_entries;
63 const SDL_Scancode *scancodes = SDL_GetScancodeTable(table, &num_entries);
64
65 if (keycode >= 0 && keycode < num_entries) {
66 scancode = scancodes[keycode];
67 }
68 return scancode;
69}
70
71#endif // SDL_INPUT_LINUXEV || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_X11
diff --git a/contrib/SDL-3.2.8/src/events/SDL_scancode_tables_c.h b/contrib/SDL-3.2.8/src/events/SDL_scancode_tables_c.h
new file mode 100644
index 0000000..c8ad5fc
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_scancode_tables_c.h
@@ -0,0 +1,33 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23typedef enum
24{
25 SDL_SCANCODE_TABLE_DARWIN,
26 SDL_SCANCODE_TABLE_LINUX,
27 SDL_SCANCODE_TABLE_XFREE86_1,
28 SDL_SCANCODE_TABLE_XFREE86_2,
29 SDL_SCANCODE_TABLE_XVNC,
30} SDL_ScancodeTable;
31
32extern const SDL_Scancode *SDL_GetScancodeTable(SDL_ScancodeTable table, int *num_entries);
33extern SDL_Scancode SDL_GetScancodeFromTable(SDL_ScancodeTable table, int keycode);
diff --git a/contrib/SDL-3.2.8/src/events/SDL_touch.c b/contrib/SDL-3.2.8/src/events/SDL_touch.c
new file mode 100644
index 0000000..ec4acb1
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_touch.c
@@ -0,0 +1,500 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// General touch handling code for SDL
24
25#include "SDL_events_c.h"
26#include "../video/SDL_sysvideo.h"
27
28static int SDL_num_touch = 0;
29static SDL_Touch **SDL_touchDevices = NULL;
30
31// for mapping touch events to mice
32static bool finger_touching = false;
33static SDL_FingerID track_fingerid;
34static SDL_TouchID track_touchid;
35
36// Public functions
37bool SDL_InitTouch(void)
38{
39 return true;
40}
41
42bool SDL_TouchDevicesAvailable(void)
43{
44 return SDL_num_touch > 0;
45}
46
47SDL_TouchID *SDL_GetTouchDevices(int *count)
48{
49 if (count) {
50 *count = 0;
51 }
52
53 const int total = SDL_num_touch;
54 SDL_TouchID *result = (SDL_TouchID *) SDL_malloc(sizeof (SDL_TouchID) * (total + 1));
55 if (result) {
56 for (int i = 0; i < total; i++) {
57 result[i] = SDL_touchDevices[i]->id;
58 }
59 result[total] = 0;
60 if (count) {
61 *count = SDL_num_touch;
62 }
63 }
64
65 return result;
66}
67
68static int SDL_GetTouchIndex(SDL_TouchID id)
69{
70 int index;
71 SDL_Touch *touch;
72
73 for (index = 0; index < SDL_num_touch; ++index) {
74 touch = SDL_touchDevices[index];
75 if (touch->id == id) {
76 return index;
77 }
78 }
79 return -1;
80}
81
82SDL_Touch *SDL_GetTouch(SDL_TouchID id)
83{
84 int index = SDL_GetTouchIndex(id);
85 if (index < 0 || index >= SDL_num_touch) {
86 if (SDL_GetVideoDevice()->ResetTouch != NULL) {
87 SDL_SetError("Unknown touch id %d, resetting", (int)id);
88 (SDL_GetVideoDevice()->ResetTouch)(SDL_GetVideoDevice());
89 } else {
90 SDL_SetError("Unknown touch device id %d, cannot reset", (int)id);
91 }
92 return NULL;
93 }
94 return SDL_touchDevices[index];
95}
96
97const char *SDL_GetTouchDeviceName(SDL_TouchID id)
98{
99 SDL_Touch *touch = SDL_GetTouch(id);
100 if (!touch) {
101 return NULL;
102 }
103 return SDL_GetPersistentString(touch->name);
104}
105
106SDL_TouchDeviceType SDL_GetTouchDeviceType(SDL_TouchID id)
107{
108 SDL_Touch *touch = SDL_GetTouch(id);
109 return touch ? touch->type : SDL_TOUCH_DEVICE_INVALID;
110}
111
112static int SDL_GetFingerIndex(const SDL_Touch *touch, SDL_FingerID fingerid)
113{
114 int index;
115 for (index = 0; index < touch->num_fingers; ++index) {
116 if (touch->fingers[index]->id == fingerid) {
117 return index;
118 }
119 }
120 return -1;
121}
122
123static SDL_Finger *SDL_GetFinger(const SDL_Touch *touch, SDL_FingerID id)
124{
125 int index = SDL_GetFingerIndex(touch, id);
126 if (index < 0 || index >= touch->num_fingers) {
127 return NULL;
128 }
129 return touch->fingers[index];
130}
131
132SDL_Finger **SDL_GetTouchFingers(SDL_TouchID touchID, int *count)
133{
134 SDL_Finger **fingers;
135 SDL_Finger *finger_data;
136
137 if (count) {
138 *count = 0;
139 }
140
141 SDL_Touch *touch = SDL_GetTouch(touchID);
142 if (!touch) {
143 return NULL;
144 }
145
146 // Create a snapshot of the current finger state
147 fingers = (SDL_Finger **)SDL_malloc((touch->num_fingers + 1) * sizeof(*fingers) + touch->num_fingers * sizeof(**fingers));
148 if (!fingers) {
149 return NULL;
150 }
151 finger_data = (SDL_Finger *)(fingers + (touch->num_fingers + 1));
152
153 for (int i = 0; i < touch->num_fingers; ++i) {
154 fingers[i] = &finger_data[i];
155 SDL_copyp(fingers[i], touch->fingers[i]);
156 }
157 fingers[touch->num_fingers] = NULL;
158
159 if (count) {
160 *count = touch->num_fingers;
161 }
162 return fingers;
163}
164
165int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
166{
167 SDL_Touch **touchDevices;
168 int index;
169
170 SDL_assert(touchID != 0);
171
172 index = SDL_GetTouchIndex(touchID);
173 if (index >= 0) {
174 return index;
175 }
176
177 // Add the touch to the list of touch
178 touchDevices = (SDL_Touch **)SDL_realloc(SDL_touchDevices,
179 (SDL_num_touch + 1) * sizeof(*touchDevices));
180 if (!touchDevices) {
181 return -1;
182 }
183
184 SDL_touchDevices = touchDevices;
185 index = SDL_num_touch;
186
187 SDL_touchDevices[index] = (SDL_Touch *)SDL_malloc(sizeof(*SDL_touchDevices[index]));
188 if (!SDL_touchDevices[index]) {
189 return -1;
190 }
191
192 // Added touch to list
193 ++SDL_num_touch;
194
195 // we're setting the touch properties
196 SDL_touchDevices[index]->id = touchID;
197 SDL_touchDevices[index]->type = type;
198 SDL_touchDevices[index]->num_fingers = 0;
199 SDL_touchDevices[index]->max_fingers = 0;
200 SDL_touchDevices[index]->fingers = NULL;
201 SDL_touchDevices[index]->name = SDL_strdup(name ? name : "");
202
203 return index;
204}
205
206static bool SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
207{
208 SDL_Finger *finger;
209
210 SDL_assert(fingerid != 0);
211
212 if (touch->num_fingers == touch->max_fingers) {
213 SDL_Finger **new_fingers;
214 new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers + 1) * sizeof(*touch->fingers));
215 if (!new_fingers) {
216 return false;
217 }
218 touch->fingers = new_fingers;
219 touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger));
220 if (!touch->fingers[touch->max_fingers]) {
221 return false;
222 }
223 touch->max_fingers++;
224 }
225
226 finger = touch->fingers[touch->num_fingers++];
227 finger->id = fingerid;
228 finger->x = x;
229 finger->y = y;
230 finger->pressure = pressure;
231 return true;
232}
233
234static void SDL_DelFinger(SDL_Touch *touch, SDL_FingerID fingerid)
235{
236 int index = SDL_GetFingerIndex(touch, fingerid);
237 if (index < 0) {
238 return;
239 }
240
241 --touch->num_fingers;
242 if (index < (touch->num_fingers)) {
243 // Move the deleted finger to just past the end of the active fingers array and shift the active fingers by one.
244 // This ensures that the descriptor for the now-deleted finger is located at `touch->fingers[touch->num_fingers]`
245 // and is ready for use in SDL_AddFinger.
246 SDL_Finger *deleted_finger = touch->fingers[index];
247 SDL_memmove(&touch->fingers[index], &touch->fingers[index + 1], (touch->num_fingers - index) * sizeof(touch->fingers[index]));
248 touch->fingers[touch->num_fingers] = deleted_finger;
249 }
250}
251
252void SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, SDL_EventType type, float x, float y, float pressure)
253{
254 SDL_Finger *finger;
255 bool down = (type == SDL_EVENT_FINGER_DOWN);
256
257 SDL_Touch *touch = SDL_GetTouch(id);
258 if (!touch) {
259 return;
260 }
261
262 SDL_Mouse *mouse = SDL_GetMouse();
263
264 // SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events
265 // SDL_HINT_VITA_TOUCH_MOUSE_DEVICE: controlling which touchpad should generate synthetic mouse events, PSVita-only
266 {
267 // FIXME: maybe we should only restrict to a few SDL_TouchDeviceType
268 if ((id != SDL_MOUSE_TOUCHID) && (id != SDL_PEN_TOUCHID)) {
269#ifdef SDL_PLATFORM_VITA
270 if (mouse->touch_mouse_events && ((mouse->vita_touch_mouse_device == id) || (mouse->vita_touch_mouse_device == 3))) {
271#else
272 if (mouse->touch_mouse_events) {
273#endif
274 if (window) {
275 if (down) {
276 if (finger_touching == false) {
277 float pos_x = (x * (float)window->w);
278 float pos_y = (y * (float)window->h);
279 if (pos_x < 0) {
280 pos_x = 0;
281 }
282 if (pos_x > (float)(window->w - 1)) {
283 pos_x = (float)(window->w - 1);
284 }
285 if (pos_y < 0.0f) {
286 pos_y = 0.0f;
287 }
288 if (pos_y > (float)(window->h - 1)) {
289 pos_y = (float)(window->h - 1);
290 }
291 SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, false, pos_x, pos_y);
292 SDL_SendMouseButton(timestamp, window, SDL_TOUCH_MOUSEID, SDL_BUTTON_LEFT, true);
293 }
294 } else {
295 if (finger_touching == true && track_touchid == id && track_fingerid == fingerid) {
296 SDL_SendMouseButton(timestamp, window, SDL_TOUCH_MOUSEID, SDL_BUTTON_LEFT, false);
297 }
298 }
299 }
300 if (down) {
301 if (finger_touching == false) {
302 finger_touching = true;
303 track_touchid = id;
304 track_fingerid = fingerid;
305 }
306 } else {
307 if (finger_touching == true && track_touchid == id && track_fingerid == fingerid) {
308 finger_touching = false;
309 }
310 }
311 }
312 }
313 }
314
315 // SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer
316 if (!mouse->mouse_touch_events && (id == SDL_MOUSE_TOUCHID)) {
317 return;
318 } else if (!mouse->pen_touch_events && (id == SDL_PEN_TOUCHID)) {
319 return;
320 }
321
322 finger = SDL_GetFinger(touch, fingerid);
323 if (down) {
324 if (finger) {
325 /* This finger is already down.
326 Assume the finger-up for the previous touch was lost, and send it. */
327 SDL_SendTouch(timestamp, id, fingerid, window, SDL_EVENT_FINGER_CANCELED, x, y, pressure);
328 }
329
330 if (!SDL_AddFinger(touch, fingerid, x, y, pressure)) {
331 return;
332 }
333
334 if (SDL_EventEnabled(type)) {
335 SDL_Event event;
336 event.type = type;
337 event.common.timestamp = timestamp;
338 event.tfinger.touchID = id;
339 event.tfinger.fingerID = fingerid;
340 event.tfinger.x = x;
341 event.tfinger.y = y;
342 event.tfinger.dx = 0;
343 event.tfinger.dy = 0;
344 event.tfinger.pressure = pressure;
345 event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
346 SDL_PushEvent(&event);
347 }
348 } else {
349 if (!finger) {
350 // This finger is already up
351 return;
352 }
353
354 if (SDL_EventEnabled(type)) {
355 SDL_Event event;
356 event.type = type;
357 event.common.timestamp = timestamp;
358 event.tfinger.touchID = id;
359 event.tfinger.fingerID = fingerid;
360 // I don't trust the coordinates passed on fingerUp
361 event.tfinger.x = finger->x;
362 event.tfinger.y = finger->y;
363 event.tfinger.dx = 0;
364 event.tfinger.dy = 0;
365 event.tfinger.pressure = pressure;
366 event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
367 SDL_PushEvent(&event);
368 }
369
370 SDL_DelFinger(touch, fingerid);
371 }
372}
373
374void SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window,
375 float x, float y, float pressure)
376{
377 SDL_Touch *touch;
378 SDL_Finger *finger;
379 float xrel, yrel, prel;
380
381 touch = SDL_GetTouch(id);
382 if (!touch) {
383 return;
384 }
385
386 SDL_Mouse *mouse = SDL_GetMouse();
387
388 // SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events
389 {
390 if ((id != SDL_MOUSE_TOUCHID) && (id != SDL_PEN_TOUCHID)) {
391 if (mouse->touch_mouse_events) {
392 if (window) {
393 if (finger_touching == true && track_touchid == id && track_fingerid == fingerid) {
394 float pos_x = (x * (float)window->w);
395 float pos_y = (y * (float)window->h);
396 if (pos_x < 0.0f) {
397 pos_x = 0.0f;
398 }
399 if (pos_x > (float)(window->w - 1)) {
400 pos_x = (float)(window->w - 1);
401 }
402 if (pos_y < 0.0f) {
403 pos_y = 0.0f;
404 }
405 if (pos_y > (float)(window->h - 1)) {
406 pos_y = (float)(window->h - 1);
407 }
408 SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, false, pos_x, pos_y);
409 }
410 }
411 }
412 }
413 }
414
415 // SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer
416 if (mouse->mouse_touch_events == 0) {
417 if (id == SDL_MOUSE_TOUCHID) {
418 return;
419 }
420 }
421
422 finger = SDL_GetFinger(touch, fingerid);
423 if (!finger) {
424 SDL_SendTouch(timestamp, id, fingerid, window, SDL_EVENT_FINGER_DOWN, x, y, pressure);
425 return;
426 }
427
428 xrel = x - finger->x;
429 yrel = y - finger->y;
430 prel = pressure - finger->pressure;
431
432 // Drop events that don't change state
433 if (xrel == 0.0f && yrel == 0.0f && prel == 0.0f) {
434#if 0
435 printf("Touch event didn't change state - dropped!\n");
436#endif
437 return;
438 }
439
440 // Update internal touch coordinates
441 finger->x = x;
442 finger->y = y;
443 finger->pressure = pressure;
444
445 // Post the event, if desired
446 if (SDL_EventEnabled(SDL_EVENT_FINGER_MOTION)) {
447 SDL_Event event;
448 event.type = SDL_EVENT_FINGER_MOTION;
449 event.common.timestamp = timestamp;
450 event.tfinger.touchID = id;
451 event.tfinger.fingerID = fingerid;
452 event.tfinger.x = x;
453 event.tfinger.y = y;
454 event.tfinger.dx = xrel;
455 event.tfinger.dy = yrel;
456 event.tfinger.pressure = pressure;
457 event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
458 SDL_PushEvent(&event);
459 }
460}
461
462void SDL_DelTouch(SDL_TouchID id)
463{
464 int i, index;
465 SDL_Touch *touch;
466
467 if (SDL_num_touch == 0) {
468 // We've already cleaned up, we won't find this device
469 return;
470 }
471
472 index = SDL_GetTouchIndex(id);
473 touch = SDL_GetTouch(id);
474 if (!touch) {
475 return;
476 }
477
478 for (i = 0; i < touch->max_fingers; ++i) {
479 SDL_free(touch->fingers[i]);
480 }
481 SDL_free(touch->fingers);
482 SDL_free(touch->name);
483 SDL_free(touch);
484
485 SDL_num_touch--;
486 SDL_touchDevices[index] = SDL_touchDevices[SDL_num_touch];
487}
488
489void SDL_QuitTouch(void)
490{
491 int i;
492
493 for (i = SDL_num_touch; i--;) {
494 SDL_DelTouch(SDL_touchDevices[i]->id);
495 }
496 SDL_assert(SDL_num_touch == 0);
497
498 SDL_free(SDL_touchDevices);
499 SDL_touchDevices = NULL;
500}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_touch_c.h b/contrib/SDL-3.2.8/src/events/SDL_touch_c.h
new file mode 100644
index 0000000..db2d64b
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_touch_c.h
@@ -0,0 +1,60 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_touch_c_h_
24#define SDL_touch_c_h_
25
26typedef struct SDL_Touch
27{
28 SDL_TouchID id;
29 SDL_TouchDeviceType type;
30 int num_fingers;
31 int max_fingers;
32 SDL_Finger **fingers;
33 char *name;
34} SDL_Touch;
35
36// Initialize the touch subsystem
37extern bool SDL_InitTouch(void);
38
39// Returns true if _any_ connected touch devices are known to SDL
40extern bool SDL_TouchDevicesAvailable(void);
41
42// Add a touch, returning the index of the touch, or -1 if there was an error.
43extern int SDL_AddTouch(SDL_TouchID id, SDL_TouchDeviceType type, const char *name);
44
45// Get the touch with a given id
46extern SDL_Touch *SDL_GetTouch(SDL_TouchID id);
47
48// Send a touch down/up event for a touch
49extern void SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, SDL_EventType type, float x, float y, float pressure);
50
51// Send a touch motion event for a touch
52extern void SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, float x, float y, float pressure);
53
54// Remove a touch
55extern void SDL_DelTouch(SDL_TouchID id);
56
57// Shutdown the touch subsystem
58extern void SDL_QuitTouch(void);
59
60#endif // SDL_touch_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/SDL_windowevents.c b/contrib/SDL-3.2.8/src/events/SDL_windowevents.c
new file mode 100644
index 0000000..e20cd3a
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_windowevents.c
@@ -0,0 +1,300 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// Window event handling code for SDL
24
25#include "SDL_events_c.h"
26#include "SDL_eventwatch_c.h"
27#include "SDL_mouse_c.h"
28#include "../tray/SDL_tray_utils.h"
29
30
31#define NUM_WINDOW_EVENT_WATCH_PRIORITIES (SDL_WINDOW_EVENT_WATCH_NORMAL + 1)
32
33static SDL_EventWatchList SDL_window_event_watchers[NUM_WINDOW_EVENT_WATCH_PRIORITIES];
34
35void SDL_InitWindowEventWatch(void)
36{
37 for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
38 SDL_InitEventWatchList(&SDL_window_event_watchers[i]);
39 }
40}
41
42void SDL_QuitWindowEventWatch(void)
43{
44 for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
45 SDL_QuitEventWatchList(&SDL_window_event_watchers[i]);
46 }
47}
48
49void SDL_AddWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
50{
51 SDL_AddEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
52}
53
54void SDL_RemoveWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
55{
56 SDL_RemoveEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
57}
58
59static bool SDLCALL RemoveSupercededWindowEvents(void *userdata, SDL_Event *event)
60{
61 SDL_Event *new_event = (SDL_Event *)userdata;
62
63 if (event->type == new_event->type &&
64 event->window.windowID == new_event->window.windowID) {
65 // We're about to post a new move event, drop the old one
66 return false;
67 }
68 return true;
69}
70
71bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data1, int data2)
72{
73 bool posted = false;
74
75 if (!window) {
76 return false;
77 }
78 SDL_assert(SDL_ObjectValid(window, SDL_OBJECT_TYPE_WINDOW));
79
80 if (window->is_destroying && windowevent != SDL_EVENT_WINDOW_DESTROYED) {
81 return false;
82 }
83 switch (windowevent) {
84 case SDL_EVENT_WINDOW_SHOWN:
85 if (!(window->flags & SDL_WINDOW_HIDDEN)) {
86 return false;
87 }
88 window->flags &= ~(SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED);
89 break;
90 case SDL_EVENT_WINDOW_HIDDEN:
91 if (window->flags & SDL_WINDOW_HIDDEN) {
92 return false;
93 }
94 window->flags |= SDL_WINDOW_HIDDEN;
95 break;
96 case SDL_EVENT_WINDOW_EXPOSED:
97 window->flags &= ~SDL_WINDOW_OCCLUDED;
98 break;
99 case SDL_EVENT_WINDOW_MOVED:
100 window->undefined_x = false;
101 window->undefined_y = false;
102 window->last_position_pending = false;
103 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
104 window->windowed.x = data1;
105 window->windowed.y = data2;
106
107 if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) {
108 window->floating.x = data1;
109 window->floating.y = data2;
110 }
111 }
112 if (data1 == window->x && data2 == window->y) {
113 return false;
114 }
115 window->x = data1;
116 window->y = data2;
117 break;
118 case SDL_EVENT_WINDOW_RESIZED:
119 window->last_size_pending = false;
120 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
121 window->windowed.w = data1;
122 window->windowed.h = data2;
123
124 if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) {
125 window->floating.w = data1;
126 window->floating.h = data2;
127 }
128 }
129 if (data1 == window->w && data2 == window->h) {
130 SDL_CheckWindowPixelSizeChanged(window);
131 return false;
132 }
133 window->w = data1;
134 window->h = data2;
135 break;
136 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
137 if (data1 == window->last_pixel_w && data2 == window->last_pixel_h) {
138 return false;
139 }
140 window->last_pixel_w = data1;
141 window->last_pixel_h = data2;
142 break;
143 case SDL_EVENT_WINDOW_MINIMIZED:
144 if (window->flags & SDL_WINDOW_MINIMIZED) {
145 return false;
146 }
147 window->flags &= ~SDL_WINDOW_MAXIMIZED;
148 window->flags |= SDL_WINDOW_MINIMIZED;
149 break;
150 case SDL_EVENT_WINDOW_MAXIMIZED:
151 if (window->flags & SDL_WINDOW_MAXIMIZED) {
152 return false;
153 }
154 window->flags &= ~SDL_WINDOW_MINIMIZED;
155 window->flags |= SDL_WINDOW_MAXIMIZED;
156 break;
157 case SDL_EVENT_WINDOW_RESTORED:
158 if (!(window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) {
159 return false;
160 }
161 window->flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED);
162 break;
163 case SDL_EVENT_WINDOW_MOUSE_ENTER:
164 if (window->flags & SDL_WINDOW_MOUSE_FOCUS) {
165 return false;
166 }
167 window->flags |= SDL_WINDOW_MOUSE_FOCUS;
168 break;
169 case SDL_EVENT_WINDOW_MOUSE_LEAVE:
170 if (!(window->flags & SDL_WINDOW_MOUSE_FOCUS)) {
171 return false;
172 }
173 window->flags &= ~SDL_WINDOW_MOUSE_FOCUS;
174 break;
175 case SDL_EVENT_WINDOW_FOCUS_GAINED:
176 if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
177 return false;
178 }
179 window->flags |= SDL_WINDOW_INPUT_FOCUS;
180 break;
181 case SDL_EVENT_WINDOW_FOCUS_LOST:
182 if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
183 return false;
184 }
185 window->flags &= ~SDL_WINDOW_INPUT_FOCUS;
186 break;
187 case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
188 if (data1 == 0 || (SDL_DisplayID)data1 == window->last_displayID) {
189 return false;
190 }
191 window->last_displayID = (SDL_DisplayID)data1;
192 break;
193 case SDL_EVENT_WINDOW_OCCLUDED:
194 if (window->flags & SDL_WINDOW_OCCLUDED) {
195 return false;
196 }
197 window->flags |= SDL_WINDOW_OCCLUDED;
198 break;
199 case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
200 if (window->flags & SDL_WINDOW_FULLSCREEN) {
201 return false;
202 }
203 window->flags |= SDL_WINDOW_FULLSCREEN;
204 break;
205 case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
206 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
207 return false;
208 }
209 window->flags &= ~SDL_WINDOW_FULLSCREEN;
210 break;
211 default:
212 break;
213 }
214
215 // Post the event, if desired
216 SDL_Event event;
217 event.type = windowevent;
218 event.common.timestamp = 0;
219 event.window.data1 = data1;
220 event.window.data2 = data2;
221 event.window.windowID = window->id;
222
223 SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_EARLY], &event);
224 SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_NORMAL], &event);
225
226 if (SDL_EventEnabled(windowevent)) {
227 // Fixes queue overflow with move/resize events that aren't processed
228 if (windowevent == SDL_EVENT_WINDOW_MOVED ||
229 windowevent == SDL_EVENT_WINDOW_RESIZED ||
230 windowevent == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED ||
231 windowevent == SDL_EVENT_WINDOW_SAFE_AREA_CHANGED ||
232 windowevent == SDL_EVENT_WINDOW_EXPOSED ||
233 windowevent == SDL_EVENT_WINDOW_OCCLUDED) {
234 SDL_FilterEvents(RemoveSupercededWindowEvents, &event);
235 }
236 posted = SDL_PushEvent(&event);
237 }
238
239 switch (windowevent) {
240 case SDL_EVENT_WINDOW_SHOWN:
241 SDL_OnWindowShown(window);
242 break;
243 case SDL_EVENT_WINDOW_HIDDEN:
244 SDL_OnWindowHidden(window);
245 break;
246 case SDL_EVENT_WINDOW_MOVED:
247 SDL_OnWindowMoved(window);
248 break;
249 case SDL_EVENT_WINDOW_RESIZED:
250 SDL_OnWindowResized(window);
251 break;
252 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
253 SDL_OnWindowPixelSizeChanged(window);
254 break;
255 case SDL_EVENT_WINDOW_MINIMIZED:
256 SDL_OnWindowMinimized(window);
257 break;
258 case SDL_EVENT_WINDOW_MAXIMIZED:
259 SDL_OnWindowMaximized(window);
260 break;
261 case SDL_EVENT_WINDOW_RESTORED:
262 SDL_OnWindowRestored(window);
263 break;
264 case SDL_EVENT_WINDOW_MOUSE_ENTER:
265 SDL_OnWindowEnter(window);
266 break;
267 case SDL_EVENT_WINDOW_MOUSE_LEAVE:
268 SDL_OnWindowLeave(window);
269 break;
270 case SDL_EVENT_WINDOW_FOCUS_GAINED:
271 SDL_OnWindowFocusGained(window);
272 break;
273 case SDL_EVENT_WINDOW_FOCUS_LOST:
274 SDL_OnWindowFocusLost(window);
275 break;
276 case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
277 SDL_OnWindowDisplayChanged(window);
278 break;
279 default:
280 break;
281 }
282
283 if (windowevent == SDL_EVENT_WINDOW_CLOSE_REQUESTED && !window->parent && !SDL_HasActiveTrays()) {
284 int toplevel_count = 0;
285 SDL_Window *n;
286 for (n = SDL_GetVideoDevice()->windows; n; n = n->next) {
287 if (!n->parent && !(n->flags & SDL_WINDOW_HIDDEN)) {
288 ++toplevel_count;
289 }
290 }
291
292 if (toplevel_count <= 1) {
293 if (SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) {
294 SDL_SendQuit(); // This is the last toplevel window in the list so send the SDL_EVENT_QUIT event
295 }
296 }
297 }
298
299 return posted;
300}
diff --git a/contrib/SDL-3.2.8/src/events/SDL_windowevents_c.h b/contrib/SDL-3.2.8/src/events/SDL_windowevents_c.h
new file mode 100644
index 0000000..7204305
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_windowevents_c.h
@@ -0,0 +1,39 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_windowevents_c_h_
24#define SDL_windowevents_c_h_
25
26typedef enum
27{
28 SDL_WINDOW_EVENT_WATCH_EARLY,
29 SDL_WINDOW_EVENT_WATCH_NORMAL
30} SDL_WindowEventWatchPriority;
31
32extern void SDL_InitWindowEventWatch(void);
33extern void SDL_QuitWindowEventWatch(void);
34extern void SDL_AddWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata);
35extern void SDL_RemoveWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata);
36
37extern bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data1, int data2);
38
39#endif // SDL_windowevents_c_h_
diff --git a/contrib/SDL-3.2.8/src/events/blank_cursor.h b/contrib/SDL-3.2.8/src/events/blank_cursor.h
new file mode 100644
index 0000000..d8d9b4d
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/blank_cursor.h
@@ -0,0 +1,31 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
23 * A default blank 8x8 cursor */
24
25#define BLANK_CWIDTH 8
26#define BLANK_CHEIGHT 8
27#define BLANK_CHOTX 0
28#define BLANK_CHOTY 0
29
30static const unsigned char blank_cdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
31static const unsigned char blank_cmask[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
diff --git a/contrib/SDL-3.2.8/src/events/default_cursor.h b/contrib/SDL-3.2.8/src/events/default_cursor.h
new file mode 100644
index 0000000..9a76f94
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/default_cursor.h
@@ -0,0 +1,113 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
23 * Default cursor - it happens to be the Mac cursor, but could be anything */
24
25#define DEFAULT_CWIDTH 16
26#define DEFAULT_CHEIGHT 16
27#define DEFAULT_CHOTX 0
28#define DEFAULT_CHOTY 0
29
30// Added a real MacOS cursor, at the request of Luc-Olivier de Charrière
31#define USE_MACOS_CURSOR
32
33#ifdef USE_MACOS_CURSOR
34
35static const unsigned char default_cdata[] = {
36 0x00, 0x00,
37 0x40, 0x00,
38 0x60, 0x00,
39 0x70, 0x00,
40 0x78, 0x00,
41 0x7C, 0x00,
42 0x7E, 0x00,
43 0x7F, 0x00,
44 0x7F, 0x80,
45 0x7C, 0x00,
46 0x6C, 0x00,
47 0x46, 0x00,
48 0x06, 0x00,
49 0x03, 0x00,
50 0x03, 0x00,
51 0x00, 0x00
52};
53
54static const unsigned char default_cmask[] = {
55 0xC0, 0x00,
56 0xE0, 0x00,
57 0xF0, 0x00,
58 0xF8, 0x00,
59 0xFC, 0x00,
60 0xFE, 0x00,
61 0xFF, 0x00,
62 0xFF, 0x80,
63 0xFF, 0xC0,
64 0xFF, 0xE0,
65 0xFE, 0x00,
66 0xEF, 0x00,
67 0xCF, 0x00,
68 0x87, 0x80,
69 0x07, 0x80,
70 0x03, 0x00
71};
72
73#else
74
75static const unsigned char default_cdata[] = {
76 0x00, 0x00,
77 0x40, 0x00,
78 0x60, 0x00,
79 0x70, 0x00,
80 0x78, 0x00,
81 0x7C, 0x00,
82 0x7E, 0x00,
83 0x7F, 0x00,
84 0x7F, 0x80,
85 0x7C, 0x00,
86 0x6C, 0x00,
87 0x46, 0x00,
88 0x06, 0x00,
89 0x03, 0x00,
90 0x03, 0x00,
91 0x00, 0x00
92};
93
94static const unsigned char default_cmask[] = {
95 0x40, 0x00,
96 0xE0, 0x00,
97 0xF0, 0x00,
98 0xF8, 0x00,
99 0xFC, 0x00,
100 0xFE, 0x00,
101 0xFF, 0x00,
102 0xFF, 0x80,
103 0xFF, 0xC0,
104 0xFF, 0x80,
105 0xFE, 0x00,
106 0xEF, 0x00,
107 0x4F, 0x00,
108 0x07, 0x80,
109 0x07, 0x80,
110 0x03, 0x00
111};
112
113#endif // USE_MACOS_CURSOR
diff --git a/contrib/SDL-3.2.8/src/events/imKStoUCS.c b/contrib/SDL-3.2.8/src/events/imKStoUCS.c
new file mode 100644
index 0000000..503abb0
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/imKStoUCS.c
@@ -0,0 +1,349 @@
1/*
2Copyright (C) 2003-2006,2008 Jamey Sharp, Josh Triplett
3Copyright © 2009 Red Hat, Inc.
4Copyright 1990-1992,1999,2000,2004,2009,2010 Oracle and/or its affiliates.
5All rights reserved.
6
7Permission is hereby granted, free of charge, to any person obtaining a
8copy of this software and associated documentation files (the "Software"),
9to deal in the Software without restriction, including without limitation
10the rights to use, copy, modify, merge, publish, distribute, sublicense,
11and/or sell copies of the Software, and to permit persons to whom the
12Software is furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice (including the next
15paragraph) shall be included in all copies or substantial portions of the
16Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24DEALINGS IN THE SOFTWARE.
25*/
26
27#include "SDL_internal.h"
28
29#if defined(SDL_VIDEO_DRIVER_X11) || defined(SDL_VIDEO_DRIVER_WAYLAND)
30#include "imKStoUCS.h"
31
32static unsigned short const keysym_to_unicode_1a1_1ff[] = {
33 0x0104, 0x02d8, 0x0141, 0x0000, 0x013d, 0x015a, 0x0000, /* 0x01a0-0x01a7 */
34 0x0000, 0x0160, 0x015e, 0x0164, 0x0179, 0x0000, 0x017d, 0x017b, /* 0x01a8-0x01af */
35 0x0000, 0x0105, 0x02db, 0x0142, 0x0000, 0x013e, 0x015b, 0x02c7, /* 0x01b0-0x01b7 */
36 0x0000, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* 0x01b8-0x01bf */
37 0x0154, 0x0000, 0x0000, 0x0102, 0x0000, 0x0139, 0x0106, 0x0000, /* 0x01c0-0x01c7 */
38 0x010c, 0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x0000, 0x010e, /* 0x01c8-0x01cf */
39 0x0110, 0x0143, 0x0147, 0x0000, 0x0000, 0x0150, 0x0000, 0x0000, /* 0x01d0-0x01d7 */
40 0x0158, 0x016e, 0x0000, 0x0170, 0x0000, 0x0000, 0x0162, 0x0000, /* 0x01d8-0x01df */
41 0x0155, 0x0000, 0x0000, 0x0103, 0x0000, 0x013a, 0x0107, 0x0000, /* 0x01e0-0x01e7 */
42 0x010d, 0x0000, 0x0119, 0x0000, 0x011b, 0x0000, 0x0000, 0x010f, /* 0x01e8-0x01ef */
43 0x0111, 0x0144, 0x0148, 0x0000, 0x0000, 0x0151, 0x0000, 0x0000, /* 0x01f0-0x01f7 */
44 0x0159, 0x016f, 0x0000, 0x0171, 0x0000, 0x0000, 0x0163, 0x02d9 /* 0x01f8-0x01ff */
45};
46
47static unsigned short const keysym_to_unicode_2a1_2fe[] = {
48 0x0126, 0x0000, 0x0000, 0x0000, 0x0000, 0x0124, 0x0000, /* 0x02a0-0x02a7 */
49 0x0000, 0x0130, 0x0000, 0x011e, 0x0134, 0x0000, 0x0000, 0x0000, /* 0x02a8-0x02af */
50 0x0000, 0x0127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0125, 0x0000, /* 0x02b0-0x02b7 */
51 0x0000, 0x0131, 0x0000, 0x011f, 0x0135, 0x0000, 0x0000, 0x0000, /* 0x02b8-0x02bf */
52 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010a, 0x0108, 0x0000, /* 0x02c0-0x02c7 */
53 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02c8-0x02cf */
54 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0120, 0x0000, 0x0000, /* 0x02d0-0x02d7 */
55 0x011c, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x015c, 0x0000, /* 0x02d8-0x02df */
56 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010b, 0x0109, 0x0000, /* 0x02e0-0x02e7 */
57 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02e8-0x02ef */
58 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0121, 0x0000, 0x0000, /* 0x02f0-0x02f7 */
59 0x011d, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x015d /* 0x02f8-0x02ff */
60};
61
62static unsigned short const keysym_to_unicode_3a2_3fe[] = {
63 0x0138, 0x0156, 0x0000, 0x0128, 0x013b, 0x0000, /* 0x03a0-0x03a7 */
64 0x0000, 0x0000, 0x0112, 0x0122, 0x0166, 0x0000, 0x0000, 0x0000, /* 0x03a8-0x03af */
65 0x0000, 0x0000, 0x0000, 0x0157, 0x0000, 0x0129, 0x013c, 0x0000, /* 0x03b0-0x03b7 */
66 0x0000, 0x0000, 0x0113, 0x0123, 0x0167, 0x014a, 0x0000, 0x014b, /* 0x03b8-0x03bf */
67 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012e, /* 0x03c0-0x03c7 */
68 0x0000, 0x0000, 0x0000, 0x0000, 0x0116, 0x0000, 0x0000, 0x012a, /* 0x03c8-0x03cf */
69 0x0000, 0x0145, 0x014c, 0x0136, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03d0-0x03d7 */
70 0x0000, 0x0172, 0x0000, 0x0000, 0x0000, 0x0168, 0x016a, 0x0000, /* 0x03d8-0x03df */
71 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012f, /* 0x03e0-0x03e7 */
72 0x0000, 0x0000, 0x0000, 0x0000, 0x0117, 0x0000, 0x0000, 0x012b, /* 0x03e8-0x03ef */
73 0x0000, 0x0146, 0x014d, 0x0137, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03f0-0x03f7 */
74 0x0000, 0x0173, 0x0000, 0x0000, 0x0000, 0x0169, 0x016b /* 0x03f8-0x03ff */
75};
76
77static unsigned short const keysym_to_unicode_4a1_4df[] = {
78 0x3002, 0x3008, 0x3009, 0x3001, 0x30fb, 0x30f2, 0x30a1, /* 0x04a0-0x04a7 */
79 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3, /* 0x04a8-0x04af */
80 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad, /* 0x04b0-0x04b7 */
81 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd, /* 0x04b8-0x04bf */
82 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc, /* 0x04c0-0x04c7 */
83 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, /* 0x04c8-0x04cf */
84 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, /* 0x04d0-0x04d7 */
85 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c /* 0x04d8-0x04df */
86};
87
88static unsigned short const keysym_to_unicode_590_5fe[] = {
89 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06f6, 0x06f7, /* 0x0590-0x0597 */
90 0x06f8, 0x06f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0598-0x059f */
91 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x066a, 0x0670, 0x0679, /* 0x05a0-0x05a7 */
92
93 0x067e, 0x0686, 0x0688, 0x0691, 0x060c, 0x0000, 0x06d4, 0x0000, /* 0x05ac-0x05af */
94 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, /* 0x05b0-0x05b7 */
95 0x0668, 0x0669, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, /* 0x05b8-0x05bf */
96 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, /* 0x05c0-0x05c7 */
97 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, /* 0x05c8-0x05cf */
98 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, /* 0x05d0-0x05d7 */
99 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x05d8-0x05df */
100 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, /* 0x05e0-0x05e7 */
101 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, /* 0x05e8-0x05ef */
102 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0698, 0x06a4, /* 0x05f0-0x05f7 */
103 0x06a9, 0x06af, 0x06ba, 0x06be, 0x06cc, 0x06d2, 0x06c1 /* 0x05f8-0x05fe */
104};
105
106static unsigned short keysym_to_unicode_680_6ff[] = {
107 0x0492, 0x0496, 0x049a, 0x049c, 0x04a2, 0x04ae, 0x04b0, 0x04b2, /* 0x0680-0x0687 */
108 0x04b6, 0x04b8, 0x04ba, 0x0000, 0x04d8, 0x04e2, 0x04e8, 0x04ee, /* 0x0688-0x068f */
109 0x0493, 0x0497, 0x049b, 0x049d, 0x04a3, 0x04af, 0x04b1, 0x04b3, /* 0x0690-0x0697 */
110 0x04b7, 0x04b9, 0x04bb, 0x0000, 0x04d9, 0x04e3, 0x04e9, 0x04ef, /* 0x0698-0x069f */
111 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, /* 0x06a0-0x06a7 */
112 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0491, 0x045e, 0x045f, /* 0x06a8-0x06af */
113 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, /* 0x06b0-0x06b7 */
114 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0490, 0x040e, 0x040f, /* 0x06b8-0x06bf */
115 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, /* 0x06c0-0x06c7 */
116 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0x06c8-0x06cf */
117 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, /* 0x06d0-0x06d7 */
118 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0x06d8-0x06df */
119 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, /* 0x06e0-0x06e7 */
120 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0x06e8-0x06ef */
121 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, /* 0x06f0-0x06f7 */
122 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a /* 0x06f8-0x06ff */
123};
124
125static unsigned short const keysym_to_unicode_7a1_7f9[] = {
126 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, /* 0x07a0-0x07a7 */
127 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, /* 0x07a8-0x07af */
128 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, /* 0x07b0-0x07b7 */
129 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07b8-0x07bf */
130 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, /* 0x07c0-0x07c7 */
131 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, /* 0x07c8-0x07cf */
132 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, /* 0x07d0-0x07d7 */
133 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07d8-0x07df */
134 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, /* 0x07e0-0x07e7 */
135 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, /* 0x07e8-0x07ef */
136 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, /* 0x07f0-0x07f7 */
137 0x03c8, 0x03c9 /* 0x07f8-0x07ff */
138};
139
140static unsigned short const keysym_to_unicode_8a4_8fe[] = {
141 0x2320, 0x2321, 0x0000, 0x231c, /* 0x08a0-0x08a7 */
142 0x231d, 0x231e, 0x231f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08a8-0x08af */
143 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08b0-0x08b7 */
144 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222b, /* 0x08b8-0x08bf */
145 0x2234, 0x0000, 0x221e, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, /* 0x08c0-0x08c7 */
146 0x2245, 0x2246, 0x0000, 0x0000, 0x0000, 0x0000, 0x21d2, 0x0000, /* 0x08c8-0x08cf */
147 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221a, 0x0000, /* 0x08d0-0x08d7 */
148 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222a, 0x2227, 0x2228, /* 0x08d8-0x08df */
149 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e0-0x08e7 */
150 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202, /* 0x08e8-0x08ef */
151 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, /* 0x08f0-0x08f7 */
152 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193 /* 0x08f8-0x08ff */
153};
154
155static unsigned short const keysym_to_unicode_9df_9f8[] = {
156 0x2422, /* 0x09d8-0x09df */
157 0x2666, 0x25a6, 0x2409, 0x240c, 0x240d, 0x240a, 0x0000, 0x0000, /* 0x09e0-0x09e7 */
158 0x240a, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x2500, /* 0x09e8-0x09ef */
159 0x0000, 0x0000, 0x0000, 0x0000, 0x251c, 0x2524, 0x2534, 0x252c, /* 0x09f0-0x09f7 */
160 0x2502 /* 0x09f8-0x09ff */
161};
162
163static unsigned short const keysym_to_unicode_aa1_afe[] = {
164 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, /* 0x0aa0-0x0aa7 */
165 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, /* 0x0aa8-0x0aaf */
166 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, /* 0x0ab0-0x0ab7 */
167 0x2105, 0x0000, 0x0000, 0x2012, 0x2039, 0x2024, 0x203a, 0x0000, /* 0x0ab8-0x0abf */
168 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, /* 0x0ac0-0x0ac7 */
169 0x0000, 0x2122, 0x2120, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25ad, /* 0x0ac8-0x0acf */
170 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x2030, 0x2032, 0x2033, /* 0x0ad0-0x0ad7 */
171 0x0000, 0x271d, 0x0000, 0x220e, 0x25c2, 0x2023, 0x25cf, 0x25ac, /* 0x0ad8-0x0adf */
172 0x25e6, 0x25ab, 0x25ae, 0x25b5, 0x25bf, 0x2606, 0x2022, 0x25aa, /* 0x0ae0-0x0ae7 */
173 0x25b4, 0x25be, 0x261a, 0x261b, 0x2663, 0x2666, 0x2665, 0x0000, /* 0x0ae8-0x0aef */
174 0x2720, 0x2020, 0x2021, 0x2713, 0x2612, 0x266f, 0x266d, 0x2642, /* 0x0af0-0x0af7 */
175 0x2640, 0x2121, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e /* 0x0af8-0x0aff */
176};
177
178/* none of the APL keysyms match the Unicode characters */
179
180static unsigned short const keysym_to_unicode_cdf_cfa[] = {
181 0x2017, /* 0x0cd8-0x0cdf */
182 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, /* 0x0ce0-0x0ce7 */
183 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, /* 0x0ce8-0x0cef */
184 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, /* 0x0cf0-0x0cf7 */
185 0x05e8, 0x05e9, 0x05ea /* 0x0cf8-0x0cff */
186};
187
188static unsigned short const keysym_to_unicode_da1_df9[] = {
189 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, /* 0x0da0-0x0da7 */
190 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, /* 0x0da8-0x0daf */
191 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, /* 0x0db0-0x0db7 */
192 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, /* 0x0db8-0x0dbf */
193 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, /* 0x0dc0-0x0dc7 */
194 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, /* 0x0dc8-0x0dcf */
195 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, /* 0x0dd0-0x0dd7 */
196 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0e3e, 0x0e3f, /* 0x0dd8-0x0ddf */
197 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, /* 0x0de0-0x0de7 */
198 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0000, 0x0000, /* 0x0de8-0x0def */
199 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, /* 0x0df0-0x0df7 */
200 0x0e58, 0x0e59 /* 0x0df8-0x0dff */
201};
202
203static unsigned short const keysym_to_unicode_ea0_eff[] = {
204 0x0000, 0x1101, 0x1101, 0x11aa, 0x1102, 0x11ac, 0x11ad, 0x1103, /* 0x0ea0-0x0ea7 */
205 0x1104, 0x1105, 0x11b0, 0x11b1, 0x11b2, 0x11b3, 0x11b4, 0x11b5, /* 0x0ea8-0x0eaf */
206 0x11b6, 0x1106, 0x1107, 0x1108, 0x11b9, 0x1109, 0x110a, 0x110b, /* 0x0eb0-0x0eb7 */
207 0x110c, 0x110d, 0x110e, 0x110f, 0x1110, 0x1111, 0x1112, 0x1161, /* 0x0eb8-0x0ebf */
208 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169, /* 0x0ec0-0x0ec7 */
209 0x116a, 0x116b, 0x116c, 0x116d, 0x116e, 0x116f, 0x1170, 0x1171, /* 0x0ec8-0x0ecf */
210 0x1172, 0x1173, 0x1174, 0x1175, 0x11a8, 0x11a9, 0x11aa, 0x11ab, /* 0x0ed0-0x0ed7 */
211 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, /* 0x0ed8-0x0edf */
212 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, /* 0x0ee0-0x0ee7 */
213 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x0000, /* 0x0ee8-0x0eef */
214 0x0000, 0x0000, 0x1140, 0x0000, 0x0000, 0x1159, 0x119e, 0x0000, /* 0x0ef0-0x0ef7 */
215 0x11eb, 0x0000, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9, /* 0x0ef8-0x0eff */
216};
217
218static unsigned short keysym_to_unicode_12a1_12fe[] = {
219 0x1e02, 0x1e03, 0x0000, 0x0000, 0x0000, 0x1e0a, 0x0000, /* 0x12a0-0x12a7 */
220 0x1e80, 0x0000, 0x1e82, 0x1e0b, 0x1ef2, 0x0000, 0x0000, 0x0000, /* 0x12a8-0x12af */
221 0x1e1e, 0x1e1f, 0x0000, 0x0000, 0x1e40, 0x1e41, 0x0000, 0x1e56, /* 0x12b0-0x12b7 */
222 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, /* 0x12b8-0x12bf */
223 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c0-0x12c7 */
224 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c8-0x12cf */
225 0x0174, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6a, /* 0x12d0-0x12d7 */
226 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0176, 0x0000, /* 0x12d8-0x12df */
227 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e0-0x12e7 */
228 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e8-0x12ef */
229 0x0175, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6b, /* 0x12f0-0x12f7 */
230 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0177 /* 0x12f0-0x12ff */
231};
232
233static unsigned short const keysym_to_unicode_13bc_13be[] = {
234 0x0152, 0x0153, 0x0178 /* 0x13b8-0x13bf */
235};
236
237static unsigned short keysym_to_unicode_14a1_14ff[] = {
238 0x2741, 0x00a7, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab, /* 0x14a0-0x14a7 */
239 0x2014, 0x002e, 0x055d, 0x002c, 0x2013, 0x058a, 0x2026, 0x055c, /* 0x14a8-0x14af */
240 0x055b, 0x055e, 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563, /* 0x14b0-0x14b7 */
241 0x0534, 0x0564, 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567, /* 0x14b8-0x14bf */
242 0x0538, 0x0568, 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b, /* 0x14c0-0x14c7 */
243 0x053c, 0x056c, 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f, /* 0x14c8-0x14cf */
244 0x0540, 0x0570, 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573, /* 0x14d0-0x14d7 */
245 0x0544, 0x0574, 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577, /* 0x14d8-0x14df */
246 0x0548, 0x0578, 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b, /* 0x14e0-0x14e7 */
247 0x054c, 0x057c, 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f, /* 0x14e8-0x14ef */
248 0x0550, 0x0580, 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583, /* 0x14f0-0x14f7 */
249 0x0554, 0x0584, 0x0555, 0x0585, 0x0556, 0x0586, 0x2019, 0x0027, /* 0x14f8-0x14ff */
250};
251
252static unsigned short keysym_to_unicode_15d0_15f6[] = {
253 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, /* 0x15d0-0x15d7 */
254 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, /* 0x15d8-0x15df */
255 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, /* 0x15e0-0x15e7 */
256 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, /* 0x15e8-0x15ef */
257 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6 /* 0x15f0-0x15f7 */
258};
259
260static unsigned short keysym_to_unicode_16a0_16f6[] = {
261 0x0000, 0x0000, 0xf0a2, 0x1e8a, 0x0000, 0xf0a5, 0x012c, 0xf0a7, /* 0x16a0-0x16a7 */
262 0xf0a8, 0x01b5, 0x01e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x019f, /* 0x16a8-0x16af */
263 0x0000, 0x0000, 0xf0b2, 0x1e8b, 0x01d1, 0xf0b5, 0x012d, 0xf0b7, /* 0x16b0-0x16b7 */
264 0xf0b8, 0x01b6, 0x01e7, 0x0000, 0x0000, 0x01d2, 0x0000, 0x0275, /* 0x16b8-0x16bf */
265 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x018f, 0x0000, /* 0x16c0-0x16c7 */
266 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16c8-0x16cf */
267 0x0000, 0x1e36, 0xf0d2, 0xf0d3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d0-0x16d7 */
268 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d8-0x16df */
269 0x0000, 0x1e37, 0xf0e2, 0xf0e3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e0-0x16e7 */
270 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e8-0x16ef */
271 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0259 /* 0x16f0-0x16f6 */
272};
273
274static unsigned short const keysym_to_unicode_1e9f_1eff[] = {
275 0x0303,
276 0x1ea0, 0x1ea1, 0x1ea2, 0x1ea3, 0x1ea4, 0x1ea5, 0x1ea6, 0x1ea7, /* 0x1ea0-0x1ea7 */
277 0x1ea8, 0x1ea9, 0x1eaa, 0x1eab, 0x1eac, 0x1ead, 0x1eae, 0x1eaf, /* 0x1ea8-0x1eaf */
278 0x1eb0, 0x1eb1, 0x1eb2, 0x1eb3, 0x1eb4, 0x1eb5, 0x1eb6, 0x1eb7, /* 0x1eb0-0x1eb7 */
279 0x1eb8, 0x1eb9, 0x1eba, 0x1ebb, 0x1ebc, 0x1ebd, 0x1ebe, 0x1ebf, /* 0x1eb8-0x1ebf */
280 0x1ec0, 0x1ec1, 0x1ec2, 0x1ec3, 0x1ec4, 0x1ec5, 0x1ec6, 0x1ec7, /* 0x1ec0-0x1ec7 */
281 0x1ec8, 0x1ec9, 0x1eca, 0x1ecb, 0x1ecc, 0x1ecd, 0x1ece, 0x1ecf, /* 0x1ec8-0x1ecf */
282 0x1ed0, 0x1ed1, 0x1ed2, 0x1ed3, 0x1ed4, 0x1ed5, 0x1ed6, 0x1ed7, /* 0x1ed0-0x1ed7 */
283 0x1ed8, 0x1ed9, 0x1eda, 0x1edb, 0x1edc, 0x1edd, 0x1ede, 0x1edf, /* 0x1ed8-0x1edf */
284 0x1ee0, 0x1ee1, 0x1ee2, 0x1ee3, 0x1ee4, 0x1ee5, 0x1ee6, 0x1ee7, /* 0x1ee0-0x1ee7 */
285 0x1ee8, 0x1ee9, 0x1eea, 0x1eeb, 0x1eec, 0x1eed, 0x1eee, 0x1eef, /* 0x1ee8-0x1eef */
286 0x1ef0, 0x1ef1, 0x0300, 0x0301, 0x1ef4, 0x1ef5, 0x1ef6, 0x1ef7, /* 0x1ef0-0x1ef7 */
287 0x1ef8, 0x1ef9, 0x01a0, 0x01a1, 0x01af, 0x01b0, 0x0309, 0x0323 /* 0x1ef8-0x1eff */
288};
289
290static unsigned short const keysym_to_unicode_20a0_20ac[] = {
291 0x20a0, 0x20a1, 0x20a2, 0x20a3, 0x20a4, 0x20a5, 0x20a6, 0x20a7, /* 0x20a0-0x20a7 */
292 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac /* 0x20a8-0x20af */
293};
294
295unsigned int
296SDL_KeySymToUcs4(Uint32 keysym)
297{
298 /* 'Unicode keysym' */
299 if ((keysym & 0xff000000) == 0x01000000)
300 return (keysym & 0x00ffffff);
301
302 if (keysym > 0 && keysym < 0x100)
303 return keysym;
304 else if (keysym > 0x1a0 && keysym < 0x200)
305 return keysym_to_unicode_1a1_1ff[keysym - 0x1a1];
306 else if (keysym > 0x2a0 && keysym < 0x2ff)
307 return keysym_to_unicode_2a1_2fe[keysym - 0x2a1];
308 else if (keysym > 0x3a1 && keysym < 0x3ff)
309 return keysym_to_unicode_3a2_3fe[keysym - 0x3a2];
310 else if (keysym > 0x4a0 && keysym < 0x4e0)
311 return keysym_to_unicode_4a1_4df[keysym - 0x4a1];
312 else if (keysym > 0x589 && keysym < 0x5ff)
313 return keysym_to_unicode_590_5fe[keysym - 0x590];
314 else if (keysym > 0x67f && keysym < 0x700)
315 return keysym_to_unicode_680_6ff[keysym - 0x680];
316 else if (keysym > 0x7a0 && keysym < 0x7fa)
317 return keysym_to_unicode_7a1_7f9[keysym - 0x7a1];
318 else if (keysym > 0x8a3 && keysym < 0x8ff)
319 return keysym_to_unicode_8a4_8fe[keysym - 0x8a4];
320 else if (keysym > 0x9de && keysym < 0x9f9)
321 return keysym_to_unicode_9df_9f8[keysym - 0x9df];
322 else if (keysym > 0xaa0 && keysym < 0xaff)
323 return keysym_to_unicode_aa1_afe[keysym - 0xaa1];
324 else if (keysym > 0xcde && keysym < 0xcfb)
325 return keysym_to_unicode_cdf_cfa[keysym - 0xcdf];
326 else if (keysym > 0xda0 && keysym < 0xdfa)
327 return keysym_to_unicode_da1_df9[keysym - 0xda1];
328 else if (keysym > 0xe9f && keysym < 0xf00)
329 return keysym_to_unicode_ea0_eff[keysym - 0xea0];
330 else if (keysym > 0x12a0 && keysym < 0x12ff)
331 return keysym_to_unicode_12a1_12fe[keysym - 0x12a1];
332 else if (keysym > 0x13bb && keysym < 0x13bf)
333 return keysym_to_unicode_13bc_13be[keysym - 0x13bc];
334 else if (keysym > 0x14a0 && keysym < 0x1500)
335 return keysym_to_unicode_14a1_14ff[keysym - 0x14a1];
336 else if (keysym > 0x15cf && keysym < 0x15f7)
337 return keysym_to_unicode_15d0_15f6[keysym - 0x15d0];
338 else if (keysym > 0x169f && keysym < 0x16f7)
339 return keysym_to_unicode_16a0_16f6[keysym - 0x16a0];
340 else if (keysym > 0x1e9e && keysym < 0x1f00)
341 return keysym_to_unicode_1e9f_1eff[keysym - 0x1e9f];
342 else if (keysym > 0x209f && keysym < 0x20ad)
343 return keysym_to_unicode_20a0_20ac[keysym - 0x20a0];
344 else
345 return 0;
346}
347
348#endif /* SDL_VIDEO_DRIVER_X11 */
349
diff --git a/contrib/SDL-3.2.8/src/events/imKStoUCS.h b/contrib/SDL-3.2.8/src/events/imKStoUCS.h
new file mode 100644
index 0000000..4182c1b
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/imKStoUCS.h
@@ -0,0 +1,32 @@
1#ifndef _imKStoUCS_h
2#define _imKStoUCS_h
3
4/*
5Copyright (C) 2003-2006,2008 Jamey Sharp, Josh Triplett
6Copyright © 2009 Red Hat, Inc.
7Copyright 1990-1992,1999,2000,2004,2009,2010 Oracle and/or its affiliates.
8All rights reserved.
9
10Permission is hereby granted, free of charge, to any person obtaining a
11copy of this software and associated documentation files (the "Software"),
12to deal in the Software without restriction, including without limitation
13the rights to use, copy, modify, merge, publish, distribute, sublicense,
14and/or sell copies of the Software, and to permit persons to whom the
15Software is furnished to do so, subject to the following conditions:
16
17The above copyright notice and this permission notice (including the next
18paragraph) shall be included in all copies or substantial portions of the
19Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27DEALINGS IN THE SOFTWARE.
28*/
29
30extern unsigned int SDL_KeySymToUcs4(Uint32 keysym);
31
32#endif /* _imKStoUCS_h */
diff --git a/contrib/SDL-3.2.8/src/events/scancodes_darwin.h b/contrib/SDL-3.2.8/src/events/scancodes_darwin.h
new file mode 100644
index 0000000..c3a2d4c
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/scancodes_darwin.h
@@ -0,0 +1,159 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22/* Mac virtual key code to SDL scancode mapping table
23 Sources:
24 - Inside Macintosh: Text <http://developer.apple.com/documentation/mac/Text/Text-571.html>
25 - Apple USB keyboard driver source <http://darwinsource.opendarwin.org/10.4.6.ppc/IOHIDFamily-172.8/IOHIDFamily/Cosmo_USB2ADB.c>
26 - experimentation on various ADB and USB ISO keyboards and one ADB ANSI keyboard
27*/
28/* *INDENT-OFF* */ // clang-format off
29static const SDL_Scancode darwin_scancode_table[] = {
30 /* 0 */ SDL_SCANCODE_A,
31 /* 1 */ SDL_SCANCODE_S,
32 /* 2 */ SDL_SCANCODE_D,
33 /* 3 */ SDL_SCANCODE_F,
34 /* 4 */ SDL_SCANCODE_H,
35 /* 5 */ SDL_SCANCODE_G,
36 /* 6 */ SDL_SCANCODE_Z,
37 /* 7 */ SDL_SCANCODE_X,
38 /* 8 */ SDL_SCANCODE_C,
39 /* 9 */ SDL_SCANCODE_V,
40 /* 10 */ SDL_SCANCODE_NONUSBACKSLASH, // SDL_SCANCODE_NONUSBACKSLASH on ANSI and JIS keyboards (if this key would exist there), SDL_SCANCODE_GRAVE on ISO. (The USB keyboard driver actually translates these usage codes to different virtual key codes depending on whether the keyboard is ISO/ANSI/JIS. That's why you have to help it identify the keyboard type when you plug in a PC USB keyboard. It's a historical thing - ADB keyboards are wired this way.)
41 /* 11 */ SDL_SCANCODE_B,
42 /* 12 */ SDL_SCANCODE_Q,
43 /* 13 */ SDL_SCANCODE_W,
44 /* 14 */ SDL_SCANCODE_E,
45 /* 15 */ SDL_SCANCODE_R,
46 /* 16 */ SDL_SCANCODE_Y,
47 /* 17 */ SDL_SCANCODE_T,
48 /* 18 */ SDL_SCANCODE_1,
49 /* 19 */ SDL_SCANCODE_2,
50 /* 20 */ SDL_SCANCODE_3,
51 /* 21 */ SDL_SCANCODE_4,
52 /* 22 */ SDL_SCANCODE_6,
53 /* 23 */ SDL_SCANCODE_5,
54 /* 24 */ SDL_SCANCODE_EQUALS,
55 /* 25 */ SDL_SCANCODE_9,
56 /* 26 */ SDL_SCANCODE_7,
57 /* 27 */ SDL_SCANCODE_MINUS,
58 /* 28 */ SDL_SCANCODE_8,
59 /* 29 */ SDL_SCANCODE_0,
60 /* 30 */ SDL_SCANCODE_RIGHTBRACKET,
61 /* 31 */ SDL_SCANCODE_O,
62 /* 32 */ SDL_SCANCODE_U,
63 /* 33 */ SDL_SCANCODE_LEFTBRACKET,
64 /* 34 */ SDL_SCANCODE_I,
65 /* 35 */ SDL_SCANCODE_P,
66 /* 36 */ SDL_SCANCODE_RETURN,
67 /* 37 */ SDL_SCANCODE_L,
68 /* 38 */ SDL_SCANCODE_J,
69 /* 39 */ SDL_SCANCODE_APOSTROPHE,
70 /* 40 */ SDL_SCANCODE_K,
71 /* 41 */ SDL_SCANCODE_SEMICOLON,
72 /* 42 */ SDL_SCANCODE_BACKSLASH,
73 /* 43 */ SDL_SCANCODE_COMMA,
74 /* 44 */ SDL_SCANCODE_SLASH,
75 /* 45 */ SDL_SCANCODE_N,
76 /* 46 */ SDL_SCANCODE_M,
77 /* 47 */ SDL_SCANCODE_PERIOD,
78 /* 48 */ SDL_SCANCODE_TAB,
79 /* 49 */ SDL_SCANCODE_SPACE,
80 /* 50 */ SDL_SCANCODE_GRAVE, // SDL_SCANCODE_GRAVE on ANSI and JIS keyboards, SDL_SCANCODE_NONUSBACKSLASH on ISO (see comment about virtual key code 10 above)
81 /* 51 */ SDL_SCANCODE_BACKSPACE,
82 /* 52 */ SDL_SCANCODE_KP_ENTER, // keyboard enter on portables
83 /* 53 */ SDL_SCANCODE_ESCAPE,
84 /* 54 */ SDL_SCANCODE_RGUI,
85 /* 55 */ SDL_SCANCODE_LGUI,
86 /* 56 */ SDL_SCANCODE_LSHIFT,
87 /* 57 */ SDL_SCANCODE_CAPSLOCK,
88 /* 58 */ SDL_SCANCODE_LALT,
89 /* 59 */ SDL_SCANCODE_LCTRL,
90 /* 60 */ SDL_SCANCODE_RSHIFT,
91 /* 61 */ SDL_SCANCODE_RALT,
92 /* 62 */ SDL_SCANCODE_RCTRL,
93 /* 63 */ SDL_SCANCODE_RGUI, // fn on portables, acts as a hardware-level modifier already, so we don't generate events for it, also XK_Meta_R
94 /* 64 */ SDL_SCANCODE_F17,
95 /* 65 */ SDL_SCANCODE_KP_PERIOD,
96 /* 66 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?)
97 /* 67 */ SDL_SCANCODE_KP_MULTIPLY,
98 /* 68 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?)
99 /* 69 */ SDL_SCANCODE_KP_PLUS,
100 /* 70 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?)
101 /* 71 */ SDL_SCANCODE_NUMLOCKCLEAR,
102 /* 72 */ SDL_SCANCODE_VOLUMEUP,
103 /* 73 */ SDL_SCANCODE_VOLUMEDOWN,
104 /* 74 */ SDL_SCANCODE_MUTE,
105 /* 75 */ SDL_SCANCODE_KP_DIVIDE,
106 /* 76 */ SDL_SCANCODE_KP_ENTER, // keypad enter on external keyboards, fn-return on portables
107 /* 77 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?)
108 /* 78 */ SDL_SCANCODE_KP_MINUS,
109 /* 79 */ SDL_SCANCODE_F18,
110 /* 80 */ SDL_SCANCODE_F19,
111 /* 81 */ SDL_SCANCODE_KP_EQUALS,
112 /* 82 */ SDL_SCANCODE_KP_0,
113 /* 83 */ SDL_SCANCODE_KP_1,
114 /* 84 */ SDL_SCANCODE_KP_2,
115 /* 85 */ SDL_SCANCODE_KP_3,
116 /* 86 */ SDL_SCANCODE_KP_4,
117 /* 87 */ SDL_SCANCODE_KP_5,
118 /* 88 */ SDL_SCANCODE_KP_6,
119 /* 89 */ SDL_SCANCODE_KP_7,
120 /* 90 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?)
121 /* 91 */ SDL_SCANCODE_KP_8,
122 /* 92 */ SDL_SCANCODE_KP_9,
123 /* 93 */ SDL_SCANCODE_INTERNATIONAL3, // Cosmo_USB2ADB.c says "Yen (JIS)"
124 /* 94 */ SDL_SCANCODE_INTERNATIONAL1, // Cosmo_USB2ADB.c says "Ro (JIS)"
125 /* 95 */ SDL_SCANCODE_KP_COMMA, // Cosmo_USB2ADB.c says ", JIS only"
126 /* 96 */ SDL_SCANCODE_F5,
127 /* 97 */ SDL_SCANCODE_F6,
128 /* 98 */ SDL_SCANCODE_F7,
129 /* 99 */ SDL_SCANCODE_F3,
130 /* 100 */ SDL_SCANCODE_F8,
131 /* 101 */ SDL_SCANCODE_F9,
132 /* 102 */ SDL_SCANCODE_LANG2, // Cosmo_USB2ADB.c says "Eisu"
133 /* 103 */ SDL_SCANCODE_F11,
134 /* 104 */ SDL_SCANCODE_LANG1, // Cosmo_USB2ADB.c says "Kana"
135 /* 105 */ SDL_SCANCODE_PRINTSCREEN, // On ADB keyboards, this key is labeled "F13/print screen". Problem: USB has different usage codes for these two functions. On Apple USB keyboards, the key is labeled "F13" and sends the F13 usage code (SDL_SCANCODE_F13). I decided to use SDL_SCANCODE_PRINTSCREEN here nevertheless since SDL applications are more likely to assume the presence of a print screen key than an F13 key.
136 /* 106 */ SDL_SCANCODE_F16,
137 /* 107 */ SDL_SCANCODE_SCROLLLOCK, // F14/scroll lock, see comment about F13/print screen above
138 /* 108 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?)
139 /* 109 */ SDL_SCANCODE_F10,
140 /* 110 */ SDL_SCANCODE_APPLICATION, // windows contextual menu key, fn-enter on portables
141 /* 111 */ SDL_SCANCODE_F12,
142 /* 112 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?)
143 /* 113 */ SDL_SCANCODE_PAUSE, // F15/pause, see comment about F13/print screen above
144 /* 114 */ SDL_SCANCODE_INSERT, // the key is actually labeled "help" on Apple keyboards, and works as such in Mac OS, but it sends the "insert" usage code even on Apple USB keyboards
145 /* 115 */ SDL_SCANCODE_HOME,
146 /* 116 */ SDL_SCANCODE_PAGEUP,
147 /* 117 */ SDL_SCANCODE_DELETE,
148 /* 118 */ SDL_SCANCODE_F4,
149 /* 119 */ SDL_SCANCODE_END,
150 /* 120 */ SDL_SCANCODE_F2,
151 /* 121 */ SDL_SCANCODE_PAGEDOWN,
152 /* 122 */ SDL_SCANCODE_F1,
153 /* 123 */ SDL_SCANCODE_LEFT,
154 /* 124 */ SDL_SCANCODE_RIGHT,
155 /* 125 */ SDL_SCANCODE_DOWN,
156 /* 126 */ SDL_SCANCODE_UP,
157 /* 127 */ SDL_SCANCODE_POWER
158};
159/* *INDENT-ON* */ // clang-format on
diff --git a/contrib/SDL-3.2.8/src/events/scancodes_linux.h b/contrib/SDL-3.2.8/src/events/scancodes_linux.h
new file mode 100644
index 0000000..2deeb9a
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/scancodes_linux.h
@@ -0,0 +1,848 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23/* Linux virtual key code to SDL_Keycode mapping table
24 Sources:
25 - Linux kernel source input.h
26*/
27/* *INDENT-OFF* */ // clang-format off
28static SDL_Scancode const linux_scancode_table[] = {
29 /* 0, 0x000 */ SDL_SCANCODE_UNKNOWN, // KEY_RESERVED
30 /* 1, 0x001 */ SDL_SCANCODE_ESCAPE, // KEY_ESC
31 /* 2, 0x002 */ SDL_SCANCODE_1, // KEY_1
32 /* 3, 0x003 */ SDL_SCANCODE_2, // KEY_2
33 /* 4, 0x004 */ SDL_SCANCODE_3, // KEY_3
34 /* 5, 0x005 */ SDL_SCANCODE_4, // KEY_4
35 /* 6, 0x006 */ SDL_SCANCODE_5, // KEY_5
36 /* 7, 0x007 */ SDL_SCANCODE_6, // KEY_6
37 /* 8, 0x008 */ SDL_SCANCODE_7, // KEY_7
38 /* 9, 0x009 */ SDL_SCANCODE_8, // KEY_8
39 /* 10, 0x00a */ SDL_SCANCODE_9, // KEY_9
40 /* 11, 0x00b */ SDL_SCANCODE_0, // KEY_0
41 /* 12, 0x00c */ SDL_SCANCODE_MINUS, // KEY_MINUS
42 /* 13, 0x00d */ SDL_SCANCODE_EQUALS, // KEY_EQUAL
43 /* 14, 0x00e */ SDL_SCANCODE_BACKSPACE, // KEY_BACKSPACE
44 /* 15, 0x00f */ SDL_SCANCODE_TAB, // KEY_TAB
45 /* 16, 0x010 */ SDL_SCANCODE_Q, // KEY_Q
46 /* 17, 0x011 */ SDL_SCANCODE_W, // KEY_W
47 /* 18, 0x012 */ SDL_SCANCODE_E, // KEY_E
48 /* 19, 0x013 */ SDL_SCANCODE_R, // KEY_R
49 /* 20, 0x014 */ SDL_SCANCODE_T, // KEY_T
50 /* 21, 0x015 */ SDL_SCANCODE_Y, // KEY_Y
51 /* 22, 0x016 */ SDL_SCANCODE_U, // KEY_U
52 /* 23, 0x017 */ SDL_SCANCODE_I, // KEY_I
53 /* 24, 0x018 */ SDL_SCANCODE_O, // KEY_O
54 /* 25, 0x019 */ SDL_SCANCODE_P, // KEY_P
55 /* 26, 0x01a */ SDL_SCANCODE_LEFTBRACKET, // KEY_LEFTBRACE
56 /* 27, 0x01b */ SDL_SCANCODE_RIGHTBRACKET, // KEY_RIGHTBRACE
57 /* 28, 0x01c */ SDL_SCANCODE_RETURN, // KEY_ENTER
58 /* 29, 0x01d */ SDL_SCANCODE_LCTRL, // KEY_LEFTCTRL
59 /* 30, 0x01e */ SDL_SCANCODE_A, // KEY_A
60 /* 31, 0x01f */ SDL_SCANCODE_S, // KEY_S
61 /* 32, 0x020 */ SDL_SCANCODE_D, // KEY_D
62 /* 33, 0x021 */ SDL_SCANCODE_F, // KEY_F
63 /* 34, 0x022 */ SDL_SCANCODE_G, // KEY_G
64 /* 35, 0x023 */ SDL_SCANCODE_H, // KEY_H
65 /* 36, 0x024 */ SDL_SCANCODE_J, // KEY_J
66 /* 37, 0x025 */ SDL_SCANCODE_K, // KEY_K
67 /* 38, 0x026 */ SDL_SCANCODE_L, // KEY_L
68 /* 39, 0x027 */ SDL_SCANCODE_SEMICOLON, // KEY_SEMICOLON
69 /* 40, 0x028 */ SDL_SCANCODE_APOSTROPHE, // KEY_APOSTROPHE
70 /* 41, 0x029 */ SDL_SCANCODE_GRAVE, // KEY_GRAVE
71 /* 42, 0x02a */ SDL_SCANCODE_LSHIFT, // KEY_LEFTSHIFT
72 /* 43, 0x02b */ SDL_SCANCODE_BACKSLASH, // KEY_BACKSLASH
73 /* 44, 0x02c */ SDL_SCANCODE_Z, // KEY_Z
74 /* 45, 0x02d */ SDL_SCANCODE_X, // KEY_X
75 /* 46, 0x02e */ SDL_SCANCODE_C, // KEY_C
76 /* 47, 0x02f */ SDL_SCANCODE_V, // KEY_V
77 /* 48, 0x030 */ SDL_SCANCODE_B, // KEY_B
78 /* 49, 0x031 */ SDL_SCANCODE_N, // KEY_N
79 /* 50, 0x032 */ SDL_SCANCODE_M, // KEY_M
80 /* 51, 0x033 */ SDL_SCANCODE_COMMA, // KEY_COMMA
81 /* 52, 0x034 */ SDL_SCANCODE_PERIOD, // KEY_DOT
82 /* 53, 0x035 */ SDL_SCANCODE_SLASH, // KEY_SLASH
83 /* 54, 0x036 */ SDL_SCANCODE_RSHIFT, // KEY_RIGHTSHIFT
84 /* 55, 0x037 */ SDL_SCANCODE_KP_MULTIPLY, // KEY_KPASTERISK
85 /* 56, 0x038 */ SDL_SCANCODE_LALT, // KEY_LEFTALT
86 /* 57, 0x039 */ SDL_SCANCODE_SPACE, // KEY_SPACE
87 /* 58, 0x03a */ SDL_SCANCODE_CAPSLOCK, // KEY_CAPSLOCK
88 /* 59, 0x03b */ SDL_SCANCODE_F1, // KEY_F1
89 /* 60, 0x03c */ SDL_SCANCODE_F2, // KEY_F2
90 /* 61, 0x03d */ SDL_SCANCODE_F3, // KEY_F3
91 /* 62, 0x03e */ SDL_SCANCODE_F4, // KEY_F4
92 /* 63, 0x03f */ SDL_SCANCODE_F5, // KEY_F5
93 /* 64, 0x040 */ SDL_SCANCODE_F6, // KEY_F6
94 /* 65, 0x041 */ SDL_SCANCODE_F7, // KEY_F7
95 /* 66, 0x042 */ SDL_SCANCODE_F8, // KEY_F8
96 /* 67, 0x043 */ SDL_SCANCODE_F9, // KEY_F9
97 /* 68, 0x044 */ SDL_SCANCODE_F10, // KEY_F10
98 /* 69, 0x045 */ SDL_SCANCODE_NUMLOCKCLEAR, // KEY_NUMLOCK
99 /* 70, 0x046 */ SDL_SCANCODE_SCROLLLOCK, // KEY_SCROLLLOCK
100 /* 71, 0x047 */ SDL_SCANCODE_KP_7, // KEY_KP7
101 /* 72, 0x048 */ SDL_SCANCODE_KP_8, // KEY_KP8
102 /* 73, 0x049 */ SDL_SCANCODE_KP_9, // KEY_KP9
103 /* 74, 0x04a */ SDL_SCANCODE_KP_MINUS, // KEY_KPMINUS
104 /* 75, 0x04b */ SDL_SCANCODE_KP_4, // KEY_KP4
105 /* 76, 0x04c */ SDL_SCANCODE_KP_5, // KEY_KP5
106 /* 77, 0x04d */ SDL_SCANCODE_KP_6, // KEY_KP6
107 /* 78, 0x04e */ SDL_SCANCODE_KP_PLUS, // KEY_KPPLUS
108 /* 79, 0x04f */ SDL_SCANCODE_KP_1, // KEY_KP1
109 /* 80, 0x050 */ SDL_SCANCODE_KP_2, // KEY_KP2
110 /* 81, 0x051 */ SDL_SCANCODE_KP_3, // KEY_KP3
111 /* 82, 0x052 */ SDL_SCANCODE_KP_0, // KEY_KP0
112 /* 83, 0x053 */ SDL_SCANCODE_KP_PERIOD, // KEY_KPDOT
113 /* 84, 0x054 */ SDL_SCANCODE_UNKNOWN,
114 /* 85, 0x055 */ SDL_SCANCODE_LANG5, // KEY_ZENKAKUHANKAKU
115 /* 86, 0x056 */ SDL_SCANCODE_NONUSBACKSLASH, // KEY_102ND
116 /* 87, 0x057 */ SDL_SCANCODE_F11, // KEY_F11
117 /* 88, 0x058 */ SDL_SCANCODE_F12, // KEY_F12
118 /* 89, 0x059 */ SDL_SCANCODE_INTERNATIONAL1, // KEY_RO
119 /* 90, 0x05a */ SDL_SCANCODE_LANG3, // KEY_KATAKANA
120 /* 91, 0x05b */ SDL_SCANCODE_LANG4, // KEY_HIRAGANA
121 /* 92, 0x05c */ SDL_SCANCODE_INTERNATIONAL4, // KEY_HENKAN
122 /* 93, 0x05d */ SDL_SCANCODE_INTERNATIONAL2, // KEY_KATAKANAHIRAGANA
123 /* 94, 0x05e */ SDL_SCANCODE_INTERNATIONAL5, // KEY_MUHENKAN
124 /* 95, 0x05f */ SDL_SCANCODE_INTERNATIONAL5, // KEY_KPJPCOMMA
125 /* 96, 0x060 */ SDL_SCANCODE_KP_ENTER, // KEY_KPENTER
126 /* 97, 0x061 */ SDL_SCANCODE_RCTRL, // KEY_RIGHTCTRL
127 /* 98, 0x062 */ SDL_SCANCODE_KP_DIVIDE, // KEY_KPSLASH
128 /* 99, 0x063 */ SDL_SCANCODE_SYSREQ, // KEY_SYSRQ
129 /* 100, 0x064 */ SDL_SCANCODE_RALT, // KEY_RIGHTALT
130 /* 101, 0x065 */ SDL_SCANCODE_UNKNOWN, // KEY_LINEFEED
131 /* 102, 0x066 */ SDL_SCANCODE_HOME, // KEY_HOME
132 /* 103, 0x067 */ SDL_SCANCODE_UP, // KEY_UP
133 /* 104, 0x068 */ SDL_SCANCODE_PAGEUP, // KEY_PAGEUP
134 /* 105, 0x069 */ SDL_SCANCODE_LEFT, // KEY_LEFT
135 /* 106, 0x06a */ SDL_SCANCODE_RIGHT, // KEY_RIGHT
136 /* 107, 0x06b */ SDL_SCANCODE_END, // KEY_END
137 /* 108, 0x06c */ SDL_SCANCODE_DOWN, // KEY_DOWN
138 /* 109, 0x06d */ SDL_SCANCODE_PAGEDOWN, // KEY_PAGEDOWN
139 /* 110, 0x06e */ SDL_SCANCODE_INSERT, // KEY_INSERT
140 /* 111, 0x06f */ SDL_SCANCODE_DELETE, // KEY_DELETE
141 /* 112, 0x070 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO
142 /* 113, 0x071 */ SDL_SCANCODE_MUTE, // KEY_MUTE
143 /* 114, 0x072 */ SDL_SCANCODE_VOLUMEDOWN, // KEY_VOLUMEDOWN
144 /* 115, 0x073 */ SDL_SCANCODE_VOLUMEUP, // KEY_VOLUMEUP
145 /* 116, 0x074 */ SDL_SCANCODE_POWER, // KEY_POWER
146 /* 117, 0x075 */ SDL_SCANCODE_KP_EQUALS, // KEY_KPEQUAL
147 /* 118, 0x076 */ SDL_SCANCODE_KP_PLUSMINUS, // KEY_KPPLUSMINUS
148 /* 119, 0x077 */ SDL_SCANCODE_PAUSE, // KEY_PAUSE
149 /* 120, 0x078 */ SDL_SCANCODE_UNKNOWN, // KEY_SCALE
150 /* 121, 0x079 */ SDL_SCANCODE_KP_COMMA, // KEY_KPCOMMA
151 /* 122, 0x07a */ SDL_SCANCODE_LANG1, // KEY_HANGEUL
152 /* 123, 0x07b */ SDL_SCANCODE_LANG2, // KEY_HANJA
153 /* 124, 0x07c */ SDL_SCANCODE_INTERNATIONAL3, // KEY_YEN
154 /* 125, 0x07d */ SDL_SCANCODE_LGUI, // KEY_LEFTMETA
155 /* 126, 0x07e */ SDL_SCANCODE_RGUI, // KEY_RIGHTMETA
156 /* 127, 0x07f */ SDL_SCANCODE_APPLICATION, // KEY_COMPOSE
157 /* 128, 0x080 */ SDL_SCANCODE_STOP, // KEY_STOP
158 /* 129, 0x081 */ SDL_SCANCODE_AGAIN, // KEY_AGAIN
159 /* 130, 0x082 */ SDL_SCANCODE_AC_PROPERTIES, // KEY_PROPS
160 /* 131, 0x083 */ SDL_SCANCODE_UNDO, // KEY_UNDO
161 /* 132, 0x084 */ SDL_SCANCODE_UNKNOWN, // KEY_FRONT
162 /* 133, 0x085 */ SDL_SCANCODE_COPY, // KEY_COPY
163 /* 134, 0x086 */ SDL_SCANCODE_AC_OPEN, // KEY_OPEN
164 /* 135, 0x087 */ SDL_SCANCODE_PASTE, // KEY_PASTE
165 /* 136, 0x088 */ SDL_SCANCODE_FIND, // KEY_FIND
166 /* 137, 0x089 */ SDL_SCANCODE_CUT, // KEY_CUT
167 /* 138, 0x08a */ SDL_SCANCODE_HELP, // KEY_HELP
168 /* 139, 0x08b */ SDL_SCANCODE_MENU, // KEY_MENU
169 /* 140, 0x08c */ SDL_SCANCODE_UNKNOWN, // KEY_CALC
170 /* 141, 0x08d */ SDL_SCANCODE_UNKNOWN, // KEY_SETUP
171 /* 142, 0x08e */ SDL_SCANCODE_SLEEP, // KEY_SLEEP
172 /* 143, 0x08f */ SDL_SCANCODE_WAKE, // KEY_WAKEUP
173 /* 144, 0x090 */ SDL_SCANCODE_UNKNOWN, // KEY_FILE
174 /* 145, 0x091 */ SDL_SCANCODE_UNKNOWN, // KEY_SENDFILE
175 /* 146, 0x092 */ SDL_SCANCODE_UNKNOWN, // KEY_DELETEFILE
176 /* 147, 0x093 */ SDL_SCANCODE_UNKNOWN, // KEY_XFER
177 /* 148, 0x094 */ SDL_SCANCODE_UNKNOWN, // KEY_PROG1
178 /* 149, 0x095 */ SDL_SCANCODE_UNKNOWN, // KEY_PROG2
179 /* 150, 0x096 */ SDL_SCANCODE_UNKNOWN, // KEY_WWW
180 /* 151, 0x097 */ SDL_SCANCODE_UNKNOWN, // KEY_MSDOS
181 /* 152, 0x098 */ SDL_SCANCODE_UNKNOWN, // KEY_COFFEE
182 /* 153, 0x099 */ SDL_SCANCODE_UNKNOWN, // KEY_ROTATE_DISPLAY
183 /* 154, 0x09a */ SDL_SCANCODE_UNKNOWN, // KEY_CYCLEWINDOWS
184 /* 155, 0x09b */ SDL_SCANCODE_UNKNOWN, // KEY_MAIL
185 /* 156, 0x09c */ SDL_SCANCODE_AC_BOOKMARKS, // KEY_BOOKMARKS
186 /* 157, 0x09d */ SDL_SCANCODE_UNKNOWN, // KEY_COMPUTER
187 /* 158, 0x09e */ SDL_SCANCODE_AC_BACK, // KEY_BACK
188 /* 159, 0x09f */ SDL_SCANCODE_AC_FORWARD, // KEY_FORWARD
189 /* 160, 0x0a0 */ SDL_SCANCODE_UNKNOWN, // KEY_CLOSECD
190 /* 161, 0x0a1 */ SDL_SCANCODE_MEDIA_EJECT, // KEY_EJECTCD
191 /* 162, 0x0a2 */ SDL_SCANCODE_MEDIA_EJECT, // KEY_EJECTCLOSECD
192 /* 163, 0x0a3 */ SDL_SCANCODE_MEDIA_NEXT_TRACK, // KEY_NEXTSONG
193 /* 164, 0x0a4 */ SDL_SCANCODE_MEDIA_PLAY_PAUSE, // KEY_PLAYPAUSE
194 /* 165, 0x0a5 */ SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, // KEY_PREVIOUSSONG
195 /* 166, 0x0a6 */ SDL_SCANCODE_MEDIA_STOP, // KEY_STOPCD
196 /* 167, 0x0a7 */ SDL_SCANCODE_MEDIA_RECORD, // KEY_RECORD
197 /* 168, 0x0a8 */ SDL_SCANCODE_MEDIA_REWIND, // KEY_REWIND
198 /* 169, 0x0a9 */ SDL_SCANCODE_UNKNOWN, // KEY_PHONE
199 /* 170, 0x0aa */ SDL_SCANCODE_UNKNOWN, // KEY_ISO
200 /* 171, 0x0ab */ SDL_SCANCODE_UNKNOWN, // KEY_CONFIG
201 /* 172, 0x0ac */ SDL_SCANCODE_AC_HOME, // KEY_HOMEPAGE
202 /* 173, 0x0ad */ SDL_SCANCODE_AC_REFRESH, // KEY_REFRESH
203 /* 174, 0x0ae */ SDL_SCANCODE_AC_EXIT, // KEY_EXIT
204 /* 175, 0x0af */ SDL_SCANCODE_UNKNOWN, // KEY_MOVE
205 /* 176, 0x0b0 */ SDL_SCANCODE_UNKNOWN, // KEY_EDIT
206 /* 177, 0x0b1 */ SDL_SCANCODE_UNKNOWN, // KEY_SCROLLUP
207 /* 178, 0x0b2 */ SDL_SCANCODE_UNKNOWN, // KEY_SCROLLDOWN
208 /* 179, 0x0b3 */ SDL_SCANCODE_KP_LEFTPAREN, // KEY_KPLEFTPAREN
209 /* 180, 0x0b4 */ SDL_SCANCODE_KP_RIGHTPAREN, // KEY_KPRIGHTPAREN
210 /* 181, 0x0b5 */ SDL_SCANCODE_AC_NEW, // KEY_NEW
211 /* 182, 0x0b6 */ SDL_SCANCODE_AGAIN, // KEY_REDO
212 /* 183, 0x0b7 */ SDL_SCANCODE_F13, // KEY_F13
213 /* 184, 0x0b8 */ SDL_SCANCODE_F14, // KEY_F14
214 /* 185, 0x0b9 */ SDL_SCANCODE_F15, // KEY_F15
215 /* 186, 0x0ba */ SDL_SCANCODE_F16, // KEY_F16
216 /* 187, 0x0bb */ SDL_SCANCODE_F17, // KEY_F17
217 /* 188, 0x0bc */ SDL_SCANCODE_F18, // KEY_F18
218 /* 189, 0x0bd */ SDL_SCANCODE_F19, // KEY_F19
219 /* 190, 0x0be */ SDL_SCANCODE_F20, // KEY_F20
220 /* 191, 0x0bf */ SDL_SCANCODE_F21, // KEY_F21
221 /* 192, 0x0c0 */ SDL_SCANCODE_F22, // KEY_F22
222 /* 193, 0x0c1 */ SDL_SCANCODE_F23, // KEY_F23
223 /* 194, 0x0c2 */ SDL_SCANCODE_F24, // KEY_F24
224 /* 195, 0x0c3 */ SDL_SCANCODE_UNKNOWN,
225 /* 196, 0x0c4 */ SDL_SCANCODE_UNKNOWN,
226 /* 197, 0x0c5 */ SDL_SCANCODE_UNKNOWN,
227 /* 198, 0x0c6 */ SDL_SCANCODE_UNKNOWN,
228 /* 199, 0x0c7 */ SDL_SCANCODE_UNKNOWN,
229 /* 200, 0x0c8 */ SDL_SCANCODE_MEDIA_PLAY, // KEY_PLAYCD
230 /* 201, 0x0c9 */ SDL_SCANCODE_MEDIA_PAUSE, // KEY_PAUSECD
231 /* 202, 0x0ca */ SDL_SCANCODE_UNKNOWN, // KEY_PROG3
232 /* 203, 0x0cb */ SDL_SCANCODE_UNKNOWN, // KEY_PROG4
233 /* 204, 0x0cc */ SDL_SCANCODE_UNKNOWN, // KEY_ALL_APPLICATIONS
234 /* 205, 0x0cd */ SDL_SCANCODE_UNKNOWN, // KEY_SUSPEND
235 /* 206, 0x0ce */ SDL_SCANCODE_AC_CLOSE, // KEY_CLOSE
236 /* 207, 0x0cf */ SDL_SCANCODE_MEDIA_PLAY, // KEY_PLAY
237 /* 208, 0x0d0 */ SDL_SCANCODE_MEDIA_FAST_FORWARD, // KEY_FASTFORWARD
238 /* 209, 0x0d1 */ SDL_SCANCODE_UNKNOWN, // KEY_BASSBOOST
239 /* 210, 0x0d2 */ SDL_SCANCODE_PRINTSCREEN, // KEY_PRINT
240 /* 211, 0x0d3 */ SDL_SCANCODE_UNKNOWN, // KEY_HP
241 /* 212, 0x0d4 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA
242 /* 213, 0x0d5 */ SDL_SCANCODE_UNKNOWN, // KEY_SOUND
243 /* 214, 0x0d6 */ SDL_SCANCODE_UNKNOWN, // KEY_QUESTION
244 /* 215, 0x0d7 */ SDL_SCANCODE_UNKNOWN, // KEY_EMAIL
245 /* 216, 0x0d8 */ SDL_SCANCODE_UNKNOWN, // KEY_CHAT
246 /* 217, 0x0d9 */ SDL_SCANCODE_AC_SEARCH, // KEY_SEARCH
247 /* 218, 0x0da */ SDL_SCANCODE_UNKNOWN, // KEY_CONNECT
248 /* 219, 0x0db */ SDL_SCANCODE_UNKNOWN, // KEY_FINANCE
249 /* 220, 0x0dc */ SDL_SCANCODE_UNKNOWN, // KEY_SPORT
250 /* 221, 0x0dd */ SDL_SCANCODE_UNKNOWN, // KEY_SHOP
251 /* 222, 0x0de */ SDL_SCANCODE_ALTERASE, // KEY_ALTERASE
252 /* 223, 0x0df */ SDL_SCANCODE_CANCEL, // KEY_CANCEL
253 /* 224, 0x0e0 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESSDOWN
254 /* 225, 0x0e1 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESSUP
255 /* 226, 0x0e2 */ SDL_SCANCODE_MEDIA_SELECT, // KEY_MEDIA
256 /* 227, 0x0e3 */ SDL_SCANCODE_UNKNOWN, // KEY_SWITCHVIDEOMODE
257 /* 228, 0x0e4 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDILLUMTOGGLE
258 /* 229, 0x0e5 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDILLUMDOWN
259 /* 230, 0x0e6 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDILLUMUP
260 /* 231, 0x0e7 */ SDL_SCANCODE_UNKNOWN, // KEY_SEND
261 /* 232, 0x0e8 */ SDL_SCANCODE_UNKNOWN, // KEY_REPLY
262 /* 233, 0x0e9 */ SDL_SCANCODE_UNKNOWN, // KEY_FORWARDMAIL
263 /* 234, 0x0ea */ SDL_SCANCODE_AC_SAVE, // KEY_SAVE
264 /* 235, 0x0eb */ SDL_SCANCODE_UNKNOWN, // KEY_DOCUMENTS
265 /* 236, 0x0ec */ SDL_SCANCODE_UNKNOWN, // KEY_BATTERY
266 /* 237, 0x0ed */ SDL_SCANCODE_UNKNOWN, // KEY_BLUETOOTH
267 /* 238, 0x0ee */ SDL_SCANCODE_UNKNOWN, // KEY_WLAN
268 /* 239, 0x0ef */ SDL_SCANCODE_UNKNOWN, // KEY_UWB
269 /* 240, 0x0f0 */ SDL_SCANCODE_UNKNOWN, // KEY_UNKNOWN
270 /* 241, 0x0f1 */ SDL_SCANCODE_UNKNOWN, // KEY_VIDEO_NEXT
271 /* 242, 0x0f2 */ SDL_SCANCODE_UNKNOWN, // KEY_VIDEO_PREV
272 /* 243, 0x0f3 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_CYCLE
273 /* 244, 0x0f4 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_AUTO
274 /* 245, 0x0f5 */ SDL_SCANCODE_UNKNOWN, // KEY_DISPLAY_OFF
275 /* 246, 0x0f6 */ SDL_SCANCODE_UNKNOWN, // KEY_WWAN
276 /* 247, 0x0f7 */ SDL_SCANCODE_UNKNOWN, // KEY_RFKILL
277 /* 248, 0x0f8 */ SDL_SCANCODE_UNKNOWN, // KEY_MICMUTE
278 /* 249, 0x0f9 */ SDL_SCANCODE_UNKNOWN,
279 /* 250, 0x0fa */ SDL_SCANCODE_UNKNOWN,
280 /* 251, 0x0fb */ SDL_SCANCODE_UNKNOWN,
281 /* 252, 0x0fc */ SDL_SCANCODE_UNKNOWN,
282 /* 253, 0x0fd */ SDL_SCANCODE_UNKNOWN,
283 /* 254, 0x0fe */ SDL_SCANCODE_UNKNOWN,
284 /* 255, 0x0ff */ SDL_SCANCODE_UNKNOWN,
285 /* 256, 0x100 */ SDL_SCANCODE_UNKNOWN,
286 /* 257, 0x101 */ SDL_SCANCODE_UNKNOWN,
287 /* 258, 0x102 */ SDL_SCANCODE_UNKNOWN,
288 /* 259, 0x103 */ SDL_SCANCODE_UNKNOWN,
289 /* 260, 0x104 */ SDL_SCANCODE_UNKNOWN,
290 /* 261, 0x105 */ SDL_SCANCODE_UNKNOWN,
291 /* 262, 0x106 */ SDL_SCANCODE_UNKNOWN,
292 /* 263, 0x107 */ SDL_SCANCODE_UNKNOWN,
293 /* 264, 0x108 */ SDL_SCANCODE_UNKNOWN,
294 /* 265, 0x109 */ SDL_SCANCODE_UNKNOWN,
295 /* 266, 0x10a */ SDL_SCANCODE_UNKNOWN,
296 /* 267, 0x10b */ SDL_SCANCODE_UNKNOWN,
297 /* 268, 0x10c */ SDL_SCANCODE_UNKNOWN,
298 /* 269, 0x10d */ SDL_SCANCODE_UNKNOWN,
299 /* 270, 0x10e */ SDL_SCANCODE_UNKNOWN,
300 /* 271, 0x10f */ SDL_SCANCODE_UNKNOWN,
301 /* 272, 0x110 */ SDL_SCANCODE_UNKNOWN,
302 /* 273, 0x111 */ SDL_SCANCODE_UNKNOWN,
303 /* 274, 0x112 */ SDL_SCANCODE_UNKNOWN,
304 /* 275, 0x113 */ SDL_SCANCODE_UNKNOWN,
305 /* 276, 0x114 */ SDL_SCANCODE_UNKNOWN,
306 /* 277, 0x115 */ SDL_SCANCODE_UNKNOWN,
307 /* 278, 0x116 */ SDL_SCANCODE_UNKNOWN,
308 /* 279, 0x117 */ SDL_SCANCODE_UNKNOWN,
309 /* 280, 0x118 */ SDL_SCANCODE_UNKNOWN,
310 /* 281, 0x119 */ SDL_SCANCODE_UNKNOWN,
311 /* 282, 0x11a */ SDL_SCANCODE_UNKNOWN,
312 /* 283, 0x11b */ SDL_SCANCODE_UNKNOWN,
313 /* 284, 0x11c */ SDL_SCANCODE_UNKNOWN,
314 /* 285, 0x11d */ SDL_SCANCODE_UNKNOWN,
315 /* 286, 0x11e */ SDL_SCANCODE_UNKNOWN,
316 /* 287, 0x11f */ SDL_SCANCODE_UNKNOWN,
317 /* 288, 0x120 */ SDL_SCANCODE_UNKNOWN,
318 /* 289, 0x121 */ SDL_SCANCODE_UNKNOWN,
319 /* 290, 0x122 */ SDL_SCANCODE_UNKNOWN,
320 /* 291, 0x123 */ SDL_SCANCODE_UNKNOWN,
321 /* 292, 0x124 */ SDL_SCANCODE_UNKNOWN,
322 /* 293, 0x125 */ SDL_SCANCODE_UNKNOWN,
323 /* 294, 0x126 */ SDL_SCANCODE_UNKNOWN,
324 /* 295, 0x127 */ SDL_SCANCODE_UNKNOWN,
325 /* 296, 0x128 */ SDL_SCANCODE_UNKNOWN,
326 /* 297, 0x129 */ SDL_SCANCODE_UNKNOWN,
327 /* 298, 0x12a */ SDL_SCANCODE_UNKNOWN,
328 /* 299, 0x12b */ SDL_SCANCODE_UNKNOWN,
329 /* 300, 0x12c */ SDL_SCANCODE_UNKNOWN,
330 /* 301, 0x12d */ SDL_SCANCODE_UNKNOWN,
331 /* 302, 0x12e */ SDL_SCANCODE_UNKNOWN,
332 /* 303, 0x12f */ SDL_SCANCODE_UNKNOWN,
333 /* 304, 0x130 */ SDL_SCANCODE_UNKNOWN,
334 /* 305, 0x131 */ SDL_SCANCODE_UNKNOWN,
335 /* 306, 0x132 */ SDL_SCANCODE_UNKNOWN,
336 /* 307, 0x133 */ SDL_SCANCODE_UNKNOWN,
337 /* 308, 0x134 */ SDL_SCANCODE_UNKNOWN,
338 /* 309, 0x135 */ SDL_SCANCODE_UNKNOWN,
339 /* 310, 0x136 */ SDL_SCANCODE_UNKNOWN,
340 /* 311, 0x137 */ SDL_SCANCODE_UNKNOWN,
341 /* 312, 0x138 */ SDL_SCANCODE_UNKNOWN,
342 /* 313, 0x139 */ SDL_SCANCODE_UNKNOWN,
343 /* 314, 0x13a */ SDL_SCANCODE_UNKNOWN,
344 /* 315, 0x13b */ SDL_SCANCODE_UNKNOWN,
345 /* 316, 0x13c */ SDL_SCANCODE_UNKNOWN,
346 /* 317, 0x13d */ SDL_SCANCODE_UNKNOWN,
347 /* 318, 0x13e */ SDL_SCANCODE_UNKNOWN,
348 /* 319, 0x13f */ SDL_SCANCODE_UNKNOWN,
349 /* 320, 0x140 */ SDL_SCANCODE_UNKNOWN,
350 /* 321, 0x141 */ SDL_SCANCODE_UNKNOWN,
351 /* 322, 0x142 */ SDL_SCANCODE_UNKNOWN,
352 /* 323, 0x143 */ SDL_SCANCODE_UNKNOWN,
353 /* 324, 0x144 */ SDL_SCANCODE_UNKNOWN,
354 /* 325, 0x145 */ SDL_SCANCODE_UNKNOWN,
355 /* 326, 0x146 */ SDL_SCANCODE_UNKNOWN,
356 /* 327, 0x147 */ SDL_SCANCODE_UNKNOWN,
357 /* 328, 0x148 */ SDL_SCANCODE_UNKNOWN,
358 /* 329, 0x149 */ SDL_SCANCODE_UNKNOWN,
359 /* 330, 0x14a */ SDL_SCANCODE_UNKNOWN,
360 /* 331, 0x14b */ SDL_SCANCODE_UNKNOWN,
361 /* 332, 0x14c */ SDL_SCANCODE_UNKNOWN,
362 /* 333, 0x14d */ SDL_SCANCODE_UNKNOWN,
363 /* 334, 0x14e */ SDL_SCANCODE_UNKNOWN,
364 /* 335, 0x14f */ SDL_SCANCODE_UNKNOWN,
365 /* 336, 0x150 */ SDL_SCANCODE_UNKNOWN,
366 /* 337, 0x151 */ SDL_SCANCODE_UNKNOWN,
367 /* 338, 0x152 */ SDL_SCANCODE_UNKNOWN,
368 /* 339, 0x153 */ SDL_SCANCODE_UNKNOWN,
369 /* 340, 0x154 */ SDL_SCANCODE_UNKNOWN,
370 /* 341, 0x155 */ SDL_SCANCODE_UNKNOWN,
371 /* 342, 0x156 */ SDL_SCANCODE_UNKNOWN,
372 /* 343, 0x157 */ SDL_SCANCODE_UNKNOWN,
373 /* 344, 0x158 */ SDL_SCANCODE_UNKNOWN,
374 /* 345, 0x159 */ SDL_SCANCODE_UNKNOWN,
375 /* 346, 0x15a */ SDL_SCANCODE_UNKNOWN,
376 /* 347, 0x15b */ SDL_SCANCODE_UNKNOWN,
377 /* 348, 0x15c */ SDL_SCANCODE_UNKNOWN,
378 /* 349, 0x15d */ SDL_SCANCODE_UNKNOWN,
379 /* 350, 0x15e */ SDL_SCANCODE_UNKNOWN,
380 /* 351, 0x15f */ SDL_SCANCODE_UNKNOWN,
381 /* 352, 0x160 */ SDL_SCANCODE_UNKNOWN, // KEY_OK
382 /* 353, 0x161 */ SDL_SCANCODE_SELECT, // KEY_SELECT
383 /* 354, 0x162 */ SDL_SCANCODE_UNKNOWN, // KEY_GOTO
384 /* 355, 0x163 */ SDL_SCANCODE_CLEAR, // KEY_CLEAR
385 /* 356, 0x164 */ SDL_SCANCODE_UNKNOWN, // KEY_POWER2
386 /* 357, 0x165 */ SDL_SCANCODE_UNKNOWN, // KEY_OPTION
387 /* 358, 0x166 */ SDL_SCANCODE_UNKNOWN, // KEY_INFO
388 /* 359, 0x167 */ SDL_SCANCODE_UNKNOWN, // KEY_TIME
389 /* 360, 0x168 */ SDL_SCANCODE_UNKNOWN, // KEY_VENDOR
390 /* 361, 0x169 */ SDL_SCANCODE_UNKNOWN, // KEY_ARCHIVE
391 /* 362, 0x16a */ SDL_SCANCODE_UNKNOWN, // KEY_PROGRAM
392 /* 363, 0x16b */ SDL_SCANCODE_UNKNOWN, // KEY_CHANNEL
393 /* 364, 0x16c */ SDL_SCANCODE_UNKNOWN, // KEY_FAVORITES
394 /* 365, 0x16d */ SDL_SCANCODE_UNKNOWN, // KEY_EPG
395 /* 366, 0x16e */ SDL_SCANCODE_UNKNOWN, // KEY_PVR
396 /* 367, 0x16f */ SDL_SCANCODE_UNKNOWN, // KEY_MHP
397 /* 368, 0x170 */ SDL_SCANCODE_UNKNOWN, // KEY_LANGUAGE
398 /* 369, 0x171 */ SDL_SCANCODE_UNKNOWN, // KEY_TITLE
399 /* 370, 0x172 */ SDL_SCANCODE_UNKNOWN, // KEY_SUBTITLE
400 /* 371, 0x173 */ SDL_SCANCODE_UNKNOWN, // KEY_ANGLE
401 /* 372, 0x174 */ SDL_SCANCODE_UNKNOWN, // KEY_FULL_SCREEN
402 /* 373, 0x175 */ SDL_SCANCODE_MODE, // KEY_MODE
403 /* 374, 0x176 */ SDL_SCANCODE_UNKNOWN, // KEY_KEYBOARD
404 /* 375, 0x177 */ SDL_SCANCODE_UNKNOWN, // KEY_ASPECT_RATIO
405 /* 376, 0x178 */ SDL_SCANCODE_UNKNOWN, // KEY_PC
406 /* 377, 0x179 */ SDL_SCANCODE_UNKNOWN, // KEY_TV
407 /* 378, 0x17a */ SDL_SCANCODE_UNKNOWN, // KEY_TV2
408 /* 379, 0x17b */ SDL_SCANCODE_UNKNOWN, // KEY_VCR
409 /* 380, 0x17c */ SDL_SCANCODE_UNKNOWN, // KEY_VCR2
410 /* 381, 0x17d */ SDL_SCANCODE_UNKNOWN, // KEY_SAT
411 /* 382, 0x17e */ SDL_SCANCODE_UNKNOWN, // KEY_SAT2
412 /* 383, 0x17f */ SDL_SCANCODE_UNKNOWN, // KEY_CD
413 /* 384, 0x180 */ SDL_SCANCODE_UNKNOWN, // KEY_TAPE
414 /* 385, 0x181 */ SDL_SCANCODE_UNKNOWN, // KEY_RADIO
415 /* 386, 0x182 */ SDL_SCANCODE_UNKNOWN, // KEY_TUNER
416 /* 387, 0x183 */ SDL_SCANCODE_UNKNOWN, // KEY_PLAYER
417 /* 388, 0x184 */ SDL_SCANCODE_UNKNOWN, // KEY_TEXT
418 /* 389, 0x185 */ SDL_SCANCODE_UNKNOWN, // KEY_DVD
419 /* 390, 0x186 */ SDL_SCANCODE_UNKNOWN, // KEY_AUX
420 /* 391, 0x187 */ SDL_SCANCODE_UNKNOWN, // KEY_MP3
421 /* 392, 0x188 */ SDL_SCANCODE_UNKNOWN, // KEY_AUDIO
422 /* 393, 0x189 */ SDL_SCANCODE_UNKNOWN, // KEY_VIDEO
423 /* 394, 0x18a */ SDL_SCANCODE_UNKNOWN, // KEY_DIRECTORY
424 /* 395, 0x18b */ SDL_SCANCODE_UNKNOWN, // KEY_LIST
425 /* 396, 0x18c */ SDL_SCANCODE_UNKNOWN, // KEY_MEMO
426 /* 397, 0x18d */ SDL_SCANCODE_UNKNOWN, // KEY_CALENDAR
427 /* 398, 0x18e */ SDL_SCANCODE_UNKNOWN, // KEY_RED
428 /* 399, 0x18f */ SDL_SCANCODE_UNKNOWN, // KEY_GREEN
429 /* 400, 0x190 */ SDL_SCANCODE_UNKNOWN, // KEY_YELLOW
430 /* 401, 0x191 */ SDL_SCANCODE_UNKNOWN, // KEY_BLUE
431 /* 402, 0x192 */ SDL_SCANCODE_CHANNEL_INCREMENT, // KEY_CHANNELUP
432 /* 403, 0x193 */ SDL_SCANCODE_CHANNEL_DECREMENT, // KEY_CHANNELDOWN
433#if 0 // We don't have any mapped scancodes after this point (yet)
434 /* 404, 0x194 */ SDL_SCANCODE_UNKNOWN, // KEY_FIRST
435 /* 405, 0x195 */ SDL_SCANCODE_UNKNOWN, // KEY_LAST
436 /* 406, 0x196 */ SDL_SCANCODE_UNKNOWN, // KEY_AB
437 /* 407, 0x197 */ SDL_SCANCODE_UNKNOWN, // KEY_NEXT
438 /* 408, 0x198 */ SDL_SCANCODE_UNKNOWN, // KEY_RESTART
439 /* 409, 0x199 */ SDL_SCANCODE_UNKNOWN, // KEY_SLOW
440 /* 410, 0x19a */ SDL_SCANCODE_UNKNOWN, // KEY_SHUFFLE
441 /* 411, 0x19b */ SDL_SCANCODE_UNKNOWN, // KEY_BREAK
442 /* 412, 0x19c */ SDL_SCANCODE_UNKNOWN, // KEY_PREVIOUS
443 /* 413, 0x19d */ SDL_SCANCODE_UNKNOWN, // KEY_DIGITS
444 /* 414, 0x19e */ SDL_SCANCODE_UNKNOWN, // KEY_TEEN
445 /* 415, 0x19f */ SDL_SCANCODE_UNKNOWN, // KEY_TWEN
446 /* 416, 0x1a0 */ SDL_SCANCODE_UNKNOWN, // KEY_VIDEOPHONE
447 /* 417, 0x1a1 */ SDL_SCANCODE_UNKNOWN, // KEY_GAMES
448 /* 418, 0x1a2 */ SDL_SCANCODE_UNKNOWN, // KEY_ZOOMIN
449 /* 419, 0x1a3 */ SDL_SCANCODE_UNKNOWN, // KEY_ZOOMOUT
450 /* 420, 0x1a4 */ SDL_SCANCODE_UNKNOWN, // KEY_ZOOMRESET
451 /* 421, 0x1a5 */ SDL_SCANCODE_UNKNOWN, // KEY_WORDPROCESSOR
452 /* 422, 0x1a6 */ SDL_SCANCODE_UNKNOWN, // KEY_EDITOR
453 /* 423, 0x1a7 */ SDL_SCANCODE_UNKNOWN, // KEY_SPREADSHEET
454 /* 424, 0x1a8 */ SDL_SCANCODE_UNKNOWN, // KEY_GRAPHICSEDITOR
455 /* 425, 0x1a9 */ SDL_SCANCODE_UNKNOWN, // KEY_PRESENTATION
456 /* 426, 0x1aa */ SDL_SCANCODE_UNKNOWN, // KEY_DATABASE
457 /* 427, 0x1ab */ SDL_SCANCODE_UNKNOWN, // KEY_NEWS
458 /* 428, 0x1ac */ SDL_SCANCODE_UNKNOWN, // KEY_VOICEMAIL
459 /* 429, 0x1ad */ SDL_SCANCODE_UNKNOWN, // KEY_ADDRESSBOOK
460 /* 430, 0x1ae */ SDL_SCANCODE_UNKNOWN, // KEY_MESSENGER
461 /* 431, 0x1af */ SDL_SCANCODE_UNKNOWN, // KEY_DISPLAYTOGGLE
462 /* 432, 0x1b0 */ SDL_SCANCODE_UNKNOWN, // KEY_SPELLCHECK
463 /* 433, 0x1b1 */ SDL_SCANCODE_UNKNOWN, // KEY_LOGOFF
464 /* 434, 0x1b2 */ SDL_SCANCODE_UNKNOWN, // KEY_DOLLAR
465 /* 435, 0x1b3 */ SDL_SCANCODE_UNKNOWN, // KEY_EURO
466 /* 436, 0x1b4 */ SDL_SCANCODE_UNKNOWN, // KEY_FRAMEBACK
467 /* 437, 0x1b5 */ SDL_SCANCODE_UNKNOWN, // KEY_FRAMEFORWARD
468 /* 438, 0x1b6 */ SDL_SCANCODE_UNKNOWN, // KEY_CONTEXT_MENU
469 /* 439, 0x1b7 */ SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_REPEAT
470 /* 440, 0x1b8 */ SDL_SCANCODE_UNKNOWN, // KEY_10CHANNELSUP
471 /* 441, 0x1b9 */ SDL_SCANCODE_UNKNOWN, // KEY_10CHANNELSDOWN
472 /* 442, 0x1ba */ SDL_SCANCODE_UNKNOWN, // KEY_IMAGES
473 /* 443, 0x1bb */ SDL_SCANCODE_UNKNOWN,
474 /* 444, 0x1bc */ SDL_SCANCODE_UNKNOWN, // KEY_NOTIFICATION_CENTER
475 /* 445, 0x1bd */ SDL_SCANCODE_UNKNOWN, // KEY_PICKUP_PHONE
476 /* 446, 0x1be */ SDL_SCANCODE_UNKNOWN, // KEY_HANGUP_PHONE
477 /* 447, 0x1bf */ SDL_SCANCODE_UNKNOWN,
478 /* 448, 0x1c0 */ SDL_SCANCODE_UNKNOWN, // KEY_DEL_EOL
479 /* 449, 0x1c1 */ SDL_SCANCODE_UNKNOWN, // KEY_DEL_EOS
480 /* 450, 0x1c2 */ SDL_SCANCODE_UNKNOWN, // KEY_INS_LINE
481 /* 451, 0x1c3 */ SDL_SCANCODE_UNKNOWN, // KEY_DEL_LINE
482 /* 452, 0x1c4 */ SDL_SCANCODE_UNKNOWN,
483 /* 453, 0x1c5 */ SDL_SCANCODE_UNKNOWN,
484 /* 454, 0x1c6 */ SDL_SCANCODE_UNKNOWN,
485 /* 455, 0x1c7 */ SDL_SCANCODE_UNKNOWN,
486 /* 456, 0x1c8 */ SDL_SCANCODE_UNKNOWN,
487 /* 457, 0x1c9 */ SDL_SCANCODE_UNKNOWN,
488 /* 458, 0x1ca */ SDL_SCANCODE_UNKNOWN,
489 /* 459, 0x1cb */ SDL_SCANCODE_UNKNOWN,
490 /* 460, 0x1cc */ SDL_SCANCODE_UNKNOWN,
491 /* 461, 0x1cd */ SDL_SCANCODE_UNKNOWN,
492 /* 462, 0x1ce */ SDL_SCANCODE_UNKNOWN,
493 /* 463, 0x1cf */ SDL_SCANCODE_UNKNOWN,
494 /* 464, 0x1d0 */ SDL_SCANCODE_UNKNOWN, // KEY_FN
495 /* 465, 0x1d1 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_ESC
496 /* 466, 0x1d2 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F1
497 /* 467, 0x1d3 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F2
498 /* 468, 0x1d4 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F3
499 /* 469, 0x1d5 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F4
500 /* 470, 0x1d6 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F5
501 /* 471, 0x1d7 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F6
502 /* 472, 0x1d8 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F7
503 /* 473, 0x1d9 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F8
504 /* 474, 0x1da */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F9
505 /* 475, 0x1db */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F10
506 /* 476, 0x1dc */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F11
507 /* 477, 0x1dd */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F12
508 /* 478, 0x1de */ SDL_SCANCODE_UNKNOWN, // KEY_FN_1
509 /* 479, 0x1df */ SDL_SCANCODE_UNKNOWN, // KEY_FN_2
510 /* 480, 0x1e0 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_D
511 /* 481, 0x1e1 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_E
512 /* 482, 0x1e2 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F
513 /* 483, 0x1e3 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_S
514 /* 484, 0x1e4 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_B
515 /* 485, 0x1e5 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_RIGHT_SHIFT
516 /* 486, 0x1e6 */ SDL_SCANCODE_UNKNOWN,
517 /* 487, 0x1e7 */ SDL_SCANCODE_UNKNOWN,
518 /* 488, 0x1e8 */ SDL_SCANCODE_UNKNOWN,
519 /* 489, 0x1e9 */ SDL_SCANCODE_UNKNOWN,
520 /* 490, 0x1ea */ SDL_SCANCODE_UNKNOWN,
521 /* 491, 0x1eb */ SDL_SCANCODE_UNKNOWN,
522 /* 492, 0x1ec */ SDL_SCANCODE_UNKNOWN,
523 /* 493, 0x1ed */ SDL_SCANCODE_UNKNOWN,
524 /* 494, 0x1ee */ SDL_SCANCODE_UNKNOWN,
525 /* 495, 0x1ef */ SDL_SCANCODE_UNKNOWN,
526 /* 496, 0x1f0 */ SDL_SCANCODE_UNKNOWN,
527 /* 497, 0x1f1 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT1
528 /* 498, 0x1f2 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT2
529 /* 499, 0x1f3 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT3
530 /* 500, 0x1f4 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT4
531 /* 501, 0x1f5 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT5
532 /* 502, 0x1f6 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT6
533 /* 503, 0x1f7 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT7
534 /* 504, 0x1f8 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT8
535 /* 505, 0x1f9 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT9
536 /* 506, 0x1fa */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT10
537 /* 507, 0x1fb */ SDL_SCANCODE_UNKNOWN,
538 /* 508, 0x1fc */ SDL_SCANCODE_UNKNOWN,
539 /* 509, 0x1fd */ SDL_SCANCODE_UNKNOWN,
540 /* 510, 0x1fe */ SDL_SCANCODE_UNKNOWN,
541 /* 511, 0x1ff */ SDL_SCANCODE_UNKNOWN,
542 /* 512, 0x200 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_0
543 /* 513, 0x201 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_1
544 /* 514, 0x202 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_2
545 /* 515, 0x203 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_3
546 /* 516, 0x204 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_4
547 /* 517, 0x205 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_5
548 /* 518, 0x206 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_6
549 /* 519, 0x207 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_7
550 /* 520, 0x208 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_8
551 /* 521, 0x209 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_9
552 /* 522, 0x20a */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_STAR
553 /* 523, 0x20b */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_POUND
554 /* 524, 0x20c */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_A
555 /* 525, 0x20d */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_B
556 /* 526, 0x20e */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_C
557 /* 527, 0x20f */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_D
558 /* 528, 0x210 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_FOCUS
559 /* 529, 0x211 */ SDL_SCANCODE_UNKNOWN, // KEY_WPS_BUTTON
560 /* 530, 0x212 */ SDL_SCANCODE_UNKNOWN, // KEY_TOUCHPAD_TOGGLE
561 /* 531, 0x213 */ SDL_SCANCODE_UNKNOWN, // KEY_TOUCHPAD_ON
562 /* 532, 0x214 */ SDL_SCANCODE_UNKNOWN, // KEY_TOUCHPAD_OFF
563 /* 533, 0x215 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_ZOOMIN
564 /* 534, 0x216 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_ZOOMOUT
565 /* 535, 0x217 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_UP
566 /* 536, 0x218 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_DOWN
567 /* 537, 0x219 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_LEFT
568 /* 538, 0x21a */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_RIGHT
569 /* 539, 0x21b */ SDL_SCANCODE_UNKNOWN, // KEY_ATTENDANT_ON
570 /* 540, 0x21c */ SDL_SCANCODE_UNKNOWN, // KEY_ATTENDANT_OFF
571 /* 541, 0x21d */ SDL_SCANCODE_UNKNOWN, // KEY_ATTENDANT_TOGGLE
572 /* 542, 0x21e */ SDL_SCANCODE_UNKNOWN, // KEY_LIGHTS_TOGGLE
573 /* 543, 0x21f */ SDL_SCANCODE_UNKNOWN,
574 /* 544, 0x220 */ SDL_SCANCODE_UNKNOWN,
575 /* 545, 0x221 */ SDL_SCANCODE_UNKNOWN,
576 /* 546, 0x222 */ SDL_SCANCODE_UNKNOWN,
577 /* 547, 0x223 */ SDL_SCANCODE_UNKNOWN,
578 /* 548, 0x224 */ SDL_SCANCODE_UNKNOWN,
579 /* 549, 0x225 */ SDL_SCANCODE_UNKNOWN,
580 /* 550, 0x226 */ SDL_SCANCODE_UNKNOWN,
581 /* 551, 0x227 */ SDL_SCANCODE_UNKNOWN,
582 /* 552, 0x228 */ SDL_SCANCODE_UNKNOWN,
583 /* 553, 0x229 */ SDL_SCANCODE_UNKNOWN,
584 /* 554, 0x22a */ SDL_SCANCODE_UNKNOWN,
585 /* 555, 0x22b */ SDL_SCANCODE_UNKNOWN,
586 /* 556, 0x22c */ SDL_SCANCODE_UNKNOWN,
587 /* 557, 0x22d */ SDL_SCANCODE_UNKNOWN,
588 /* 558, 0x22e */ SDL_SCANCODE_UNKNOWN,
589 /* 559, 0x22f */ SDL_SCANCODE_UNKNOWN,
590 /* 560, 0x230 */ SDL_SCANCODE_UNKNOWN, // KEY_ALS_TOGGLE
591 /* 561, 0x231 */ SDL_SCANCODE_UNKNOWN, // KEY_ROTATE_LOCK_TOGGLE
592 /* 562, 0x232 */ SDL_SCANCODE_UNKNOWN,
593 /* 563, 0x233 */ SDL_SCANCODE_UNKNOWN,
594 /* 564, 0x234 */ SDL_SCANCODE_UNKNOWN,
595 /* 565, 0x235 */ SDL_SCANCODE_UNKNOWN,
596 /* 566, 0x236 */ SDL_SCANCODE_UNKNOWN,
597 /* 567, 0x237 */ SDL_SCANCODE_UNKNOWN,
598 /* 568, 0x238 */ SDL_SCANCODE_UNKNOWN,
599 /* 569, 0x239 */ SDL_SCANCODE_UNKNOWN,
600 /* 570, 0x23a */ SDL_SCANCODE_UNKNOWN,
601 /* 571, 0x23b */ SDL_SCANCODE_UNKNOWN,
602 /* 572, 0x23c */ SDL_SCANCODE_UNKNOWN,
603 /* 573, 0x23d */ SDL_SCANCODE_UNKNOWN,
604 /* 574, 0x23e */ SDL_SCANCODE_UNKNOWN,
605 /* 575, 0x23f */ SDL_SCANCODE_UNKNOWN,
606 /* 576, 0x240 */ SDL_SCANCODE_UNKNOWN, // KEY_BUTTONCONFIG
607 /* 577, 0x241 */ SDL_SCANCODE_UNKNOWN, // KEY_TASKMANAGER
608 /* 578, 0x242 */ SDL_SCANCODE_UNKNOWN, // KEY_JOURNAL
609 /* 579, 0x243 */ SDL_SCANCODE_UNKNOWN, // KEY_CONTROLPANEL
610 /* 580, 0x244 */ SDL_SCANCODE_UNKNOWN, // KEY_APPSELECT
611 /* 581, 0x245 */ SDL_SCANCODE_UNKNOWN, // KEY_SCREENSAVER
612 /* 582, 0x246 */ SDL_SCANCODE_UNKNOWN, // KEY_VOICECOMMAND
613 /* 583, 0x247 */ SDL_SCANCODE_UNKNOWN, // KEY_ASSISTANT
614 /* 584, 0x248 */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LAYOUT_NEXT
615 /* 585, 0x249 */ SDL_SCANCODE_UNKNOWN, // KEY_EMOJI_PICKER
616 /* 586, 0x24a */ SDL_SCANCODE_UNKNOWN, // KEY_DICTATE
617 /* 587, 0x24b */ SDL_SCANCODE_UNKNOWN,
618 /* 588, 0x24c */ SDL_SCANCODE_UNKNOWN,
619 /* 589, 0x24d */ SDL_SCANCODE_UNKNOWN,
620 /* 590, 0x24e */ SDL_SCANCODE_UNKNOWN,
621 /* 591, 0x24f */ SDL_SCANCODE_UNKNOWN,
622 /* 592, 0x250 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_MIN
623 /* 593, 0x251 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_MAX
624 /* 594, 0x252 */ SDL_SCANCODE_UNKNOWN,
625 /* 595, 0x253 */ SDL_SCANCODE_UNKNOWN,
626 /* 596, 0x254 */ SDL_SCANCODE_UNKNOWN,
627 /* 597, 0x255 */ SDL_SCANCODE_UNKNOWN,
628 /* 598, 0x256 */ SDL_SCANCODE_UNKNOWN,
629 /* 599, 0x257 */ SDL_SCANCODE_UNKNOWN,
630 /* 600, 0x258 */ SDL_SCANCODE_UNKNOWN,
631 /* 601, 0x259 */ SDL_SCANCODE_UNKNOWN,
632 /* 602, 0x25a */ SDL_SCANCODE_UNKNOWN,
633 /* 603, 0x25b */ SDL_SCANCODE_UNKNOWN,
634 /* 604, 0x25c */ SDL_SCANCODE_UNKNOWN,
635 /* 605, 0x25d */ SDL_SCANCODE_UNKNOWN,
636 /* 606, 0x25e */ SDL_SCANCODE_UNKNOWN,
637 /* 607, 0x25f */ SDL_SCANCODE_UNKNOWN,
638 /* 608, 0x260 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_PREV
639 /* 609, 0x261 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_NEXT
640 /* 610, 0x262 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_PREVGROUP
641 /* 611, 0x263 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_NEXTGROUP
642 /* 612, 0x264 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_ACCEPT
643 /* 613, 0x265 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_CANCEL
644 /* 614, 0x266 */ SDL_SCANCODE_UNKNOWN, // KEY_RIGHT_UP
645 /* 615, 0x267 */ SDL_SCANCODE_UNKNOWN, // KEY_RIGHT_DOWN
646 /* 616, 0x268 */ SDL_SCANCODE_UNKNOWN, // KEY_LEFT_UP
647 /* 617, 0x269 */ SDL_SCANCODE_UNKNOWN, // KEY_LEFT_DOWN
648 /* 618, 0x26a */ SDL_SCANCODE_UNKNOWN, // KEY_ROOT_MENU
649 /* 619, 0x26b */ SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_TOP_MENU
650 /* 620, 0x26c */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_11
651 /* 621, 0x26d */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_12
652 /* 622, 0x26e */ SDL_SCANCODE_UNKNOWN, // KEY_AUDIO_DESC
653 /* 623, 0x26f */ SDL_SCANCODE_UNKNOWN, // KEY_3D_MODE
654 /* 624, 0x270 */ SDL_SCANCODE_UNKNOWN, // KEY_NEXT_FAVORITE
655 /* 625, 0x271 */ SDL_SCANCODE_UNKNOWN, // KEY_STOP_RECORD
656 /* 626, 0x272 */ SDL_SCANCODE_UNKNOWN, // KEY_PAUSE_RECORD
657 /* 627, 0x273 */ SDL_SCANCODE_UNKNOWN, // KEY_VOD
658 /* 628, 0x274 */ SDL_SCANCODE_UNKNOWN, // KEY_UNMUTE
659 /* 629, 0x275 */ SDL_SCANCODE_UNKNOWN, // KEY_FASTREVERSE
660 /* 630, 0x276 */ SDL_SCANCODE_UNKNOWN, // KEY_SLOWREVERSE
661 /* 631, 0x277 */ SDL_SCANCODE_UNKNOWN, // KEY_DATA
662 /* 632, 0x278 */ SDL_SCANCODE_UNKNOWN, // KEY_ONSCREEN_KEYBOARD
663 /* 633, 0x279 */ SDL_SCANCODE_UNKNOWN, // KEY_PRIVACY_SCREEN_TOGGLE
664 /* 634, 0x27a */ SDL_SCANCODE_UNKNOWN, // KEY_SELECTIVE_SCREENSHOT
665 /* 635, 0x27b */ SDL_SCANCODE_UNKNOWN,
666 /* 636, 0x27c */ SDL_SCANCODE_UNKNOWN,
667 /* 637, 0x27d */ SDL_SCANCODE_UNKNOWN,
668 /* 638, 0x27e */ SDL_SCANCODE_UNKNOWN,
669 /* 639, 0x27f */ SDL_SCANCODE_UNKNOWN,
670 /* 640, 0x280 */ SDL_SCANCODE_UNKNOWN,
671 /* 641, 0x281 */ SDL_SCANCODE_UNKNOWN,
672 /* 642, 0x282 */ SDL_SCANCODE_UNKNOWN,
673 /* 643, 0x283 */ SDL_SCANCODE_UNKNOWN,
674 /* 644, 0x284 */ SDL_SCANCODE_UNKNOWN,
675 /* 645, 0x285 */ SDL_SCANCODE_UNKNOWN,
676 /* 646, 0x286 */ SDL_SCANCODE_UNKNOWN,
677 /* 647, 0x287 */ SDL_SCANCODE_UNKNOWN,
678 /* 648, 0x288 */ SDL_SCANCODE_UNKNOWN,
679 /* 649, 0x289 */ SDL_SCANCODE_UNKNOWN,
680 /* 650, 0x28a */ SDL_SCANCODE_UNKNOWN,
681 /* 651, 0x28b */ SDL_SCANCODE_UNKNOWN,
682 /* 652, 0x28c */ SDL_SCANCODE_UNKNOWN,
683 /* 653, 0x28d */ SDL_SCANCODE_UNKNOWN,
684 /* 654, 0x28e */ SDL_SCANCODE_UNKNOWN,
685 /* 655, 0x28f */ SDL_SCANCODE_UNKNOWN,
686 /* 656, 0x290 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO1
687 /* 657, 0x291 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO2
688 /* 658, 0x292 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO3
689 /* 659, 0x293 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO4
690 /* 660, 0x294 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO5
691 /* 661, 0x295 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO6
692 /* 662, 0x296 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO7
693 /* 663, 0x297 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO8
694 /* 664, 0x298 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO9
695 /* 665, 0x299 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO10
696 /* 666, 0x29a */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO11
697 /* 667, 0x29b */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO12
698 /* 668, 0x29c */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO13
699 /* 669, 0x29d */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO14
700 /* 670, 0x29e */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO15
701 /* 671, 0x29f */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO16
702 /* 672, 0x2a0 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO17
703 /* 673, 0x2a1 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO18
704 /* 674, 0x2a2 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO19
705 /* 675, 0x2a3 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO20
706 /* 676, 0x2a4 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO21
707 /* 677, 0x2a5 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO22
708 /* 678, 0x2a6 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO23
709 /* 679, 0x2a7 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO24
710 /* 680, 0x2a8 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO25
711 /* 681, 0x2a9 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO26
712 /* 682, 0x2aa */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO27
713 /* 683, 0x2ab */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO28
714 /* 684, 0x2ac */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO29
715 /* 685, 0x2ad */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO30
716 /* 686, 0x2ae */ SDL_SCANCODE_UNKNOWN,
717 /* 687, 0x2af */ SDL_SCANCODE_UNKNOWN,
718 /* 688, 0x2b0 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_RECORD_START
719 /* 689, 0x2b1 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_RECORD_STOP
720 /* 690, 0x2b2 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_PRESET_CYCLE
721 /* 691, 0x2b3 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_PRESET1
722 /* 692, 0x2b4 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_PRESET2
723 /* 693, 0x2b5 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_PRESET3
724 /* 694, 0x2b6 */ SDL_SCANCODE_UNKNOWN,
725 /* 695, 0x2b7 */ SDL_SCANCODE_UNKNOWN,
726 /* 696, 0x2b8 */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU1
727 /* 697, 0x2b9 */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU2
728 /* 698, 0x2ba */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU3
729 /* 699, 0x2bb */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU4
730 /* 700, 0x2bc */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU5
731 /* 701, 0x2bd */ SDL_SCANCODE_UNKNOWN,
732 /* 702, 0x2be */ SDL_SCANCODE_UNKNOWN,
733 /* 703, 0x2bf */ SDL_SCANCODE_UNKNOWN,
734 /* 704, 0x2c0 */ SDL_SCANCODE_UNKNOWN,
735 /* 705, 0x2c1 */ SDL_SCANCODE_UNKNOWN,
736 /* 706, 0x2c2 */ SDL_SCANCODE_UNKNOWN,
737 /* 707, 0x2c3 */ SDL_SCANCODE_UNKNOWN,
738 /* 708, 0x2c4 */ SDL_SCANCODE_UNKNOWN,
739 /* 709, 0x2c5 */ SDL_SCANCODE_UNKNOWN,
740 /* 710, 0x2c6 */ SDL_SCANCODE_UNKNOWN,
741 /* 711, 0x2c7 */ SDL_SCANCODE_UNKNOWN,
742 /* 712, 0x2c8 */ SDL_SCANCODE_UNKNOWN,
743 /* 713, 0x2c9 */ SDL_SCANCODE_UNKNOWN,
744 /* 714, 0x2ca */ SDL_SCANCODE_UNKNOWN,
745 /* 715, 0x2cb */ SDL_SCANCODE_UNKNOWN,
746 /* 716, 0x2cc */ SDL_SCANCODE_UNKNOWN,
747 /* 717, 0x2cd */ SDL_SCANCODE_UNKNOWN,
748 /* 718, 0x2ce */ SDL_SCANCODE_UNKNOWN,
749 /* 719, 0x2cf */ SDL_SCANCODE_UNKNOWN,
750 /* 720, 0x2d0 */ SDL_SCANCODE_UNKNOWN,
751 /* 721, 0x2d1 */ SDL_SCANCODE_UNKNOWN,
752 /* 722, 0x2d2 */ SDL_SCANCODE_UNKNOWN,
753 /* 723, 0x2d3 */ SDL_SCANCODE_UNKNOWN,
754 /* 724, 0x2d4 */ SDL_SCANCODE_UNKNOWN,
755 /* 725, 0x2d5 */ SDL_SCANCODE_UNKNOWN,
756 /* 726, 0x2d6 */ SDL_SCANCODE_UNKNOWN,
757 /* 727, 0x2d7 */ SDL_SCANCODE_UNKNOWN,
758 /* 728, 0x2d8 */ SDL_SCANCODE_UNKNOWN,
759 /* 729, 0x2d9 */ SDL_SCANCODE_UNKNOWN,
760 /* 730, 0x2da */ SDL_SCANCODE_UNKNOWN,
761 /* 731, 0x2db */ SDL_SCANCODE_UNKNOWN,
762 /* 732, 0x2dc */ SDL_SCANCODE_UNKNOWN,
763 /* 733, 0x2dd */ SDL_SCANCODE_UNKNOWN,
764 /* 734, 0x2de */ SDL_SCANCODE_UNKNOWN,
765 /* 735, 0x2df */ SDL_SCANCODE_UNKNOWN,
766 /* 736, 0x2e0 */ SDL_SCANCODE_UNKNOWN,
767 /* 737, 0x2e1 */ SDL_SCANCODE_UNKNOWN,
768 /* 738, 0x2e2 */ SDL_SCANCODE_UNKNOWN,
769 /* 739, 0x2e3 */ SDL_SCANCODE_UNKNOWN,
770 /* 740, 0x2e4 */ SDL_SCANCODE_UNKNOWN,
771 /* 741, 0x2e5 */ SDL_SCANCODE_UNKNOWN,
772 /* 742, 0x2e6 */ SDL_SCANCODE_UNKNOWN,
773 /* 743, 0x2e7 */ SDL_SCANCODE_UNKNOWN,
774 /* 744, 0x2e8 */ SDL_SCANCODE_UNKNOWN,
775 /* 745, 0x2e9 */ SDL_SCANCODE_UNKNOWN,
776 /* 746, 0x2ea */ SDL_SCANCODE_UNKNOWN,
777 /* 747, 0x2eb */ SDL_SCANCODE_UNKNOWN,
778 /* 748, 0x2ec */ SDL_SCANCODE_UNKNOWN,
779 /* 749, 0x2ed */ SDL_SCANCODE_UNKNOWN,
780 /* 750, 0x2ee */ SDL_SCANCODE_UNKNOWN,
781 /* 751, 0x2ef */ SDL_SCANCODE_UNKNOWN,
782 /* 752, 0x2f0 */ SDL_SCANCODE_UNKNOWN,
783 /* 753, 0x2f1 */ SDL_SCANCODE_UNKNOWN,
784 /* 754, 0x2f2 */ SDL_SCANCODE_UNKNOWN,
785 /* 755, 0x2f3 */ SDL_SCANCODE_UNKNOWN,
786 /* 756, 0x2f4 */ SDL_SCANCODE_UNKNOWN,
787 /* 757, 0x2f5 */ SDL_SCANCODE_UNKNOWN,
788 /* 758, 0x2f6 */ SDL_SCANCODE_UNKNOWN,
789 /* 759, 0x2f7 */ SDL_SCANCODE_UNKNOWN,
790 /* 760, 0x2f8 */ SDL_SCANCODE_UNKNOWN,
791 /* 761, 0x2f9 */ SDL_SCANCODE_UNKNOWN,
792 /* 762, 0x2fa */ SDL_SCANCODE_UNKNOWN,
793 /* 763, 0x2fb */ SDL_SCANCODE_UNKNOWN,
794 /* 764, 0x2fc */ SDL_SCANCODE_UNKNOWN,
795 /* 765, 0x2fd */ SDL_SCANCODE_UNKNOWN,
796 /* 766, 0x2fe */ SDL_SCANCODE_UNKNOWN,
797 /* 767, 0x2ff */ SDL_SCANCODE_UNKNOWN, // KEY_MAX
798#endif // 0
799};
800
801#if 0 // A shell script to update the Linux key names in this file
802#!/bin/bash
803
804function get_keyname
805{
806 value=$(echo "$1" | awk '{print $3}')
807 grep -F KEY_ /usr/include/linux/input-event-codes.h | while read line; do
808 read -ra fields <<<"$line"
809 if [ "${fields[2]}" = "$value" ]; then
810 echo "${fields[1]}"
811 return
812 fi
813 done
814}
815
816grep -F SDL_SCANCODE scancodes_linux.h | while read line; do
817 if [ $(echo "$line" | awk '{print NF}') -eq 5 ]; then
818 name=$(get_keyname "$line")
819 if [ "$name" != "" ]; then
820 echo " $line /* $name */"
821 continue
822 fi
823 fi
824 echo " $line"
825done
826#endif // end script
827
828#if 0 // A shell script to get comments from the Linux header for these keys
829#!/bin/bash
830
831function get_comment
832{
833 name=$(echo "$1" | awk '{print $7}')
834 if [ "$name" != "" ]; then
835 grep -E "$name\s" /usr/include/linux/input-event-codes.h | grep -F "/*" | sed 's,[^/]*/,/,'
836 fi
837}
838
839grep -F SDL_SCANCODE scancodes_linux.h | while read line; do
840 comment=$(get_comment "$line")
841 if [ "$comment" != "" ]; then
842 echo " $line $comment"
843 fi
844done
845#endif // end script
846
847
848/* *INDENT-ON* */ // clang-format on
diff --git a/contrib/SDL-3.2.8/src/events/scancodes_windows.h b/contrib/SDL-3.2.8/src/events/scancodes_windows.h
new file mode 100644
index 0000000..6f35114
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/scancodes_windows.h
@@ -0,0 +1,286 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23/*
24 * Windows scancode to SDL scancode mapping table
25 * https://learn.microsoft.com/windows/win32/inputdev/about-keyboard-input#scan-codes */
26
27/* *INDENT-OFF* */ // clang-format off
28static const SDL_Scancode windows_scancode_table[] = {
29 /*0x00*/ SDL_SCANCODE_UNKNOWN,
30 /*0x01*/ SDL_SCANCODE_ESCAPE,
31 /*0x02*/ SDL_SCANCODE_1,
32 /*0x03*/ SDL_SCANCODE_2,
33 /*0x04*/ SDL_SCANCODE_3,
34 /*0x05*/ SDL_SCANCODE_4,
35 /*0x06*/ SDL_SCANCODE_5,
36 /*0x07*/ SDL_SCANCODE_6,
37 /*0x08*/ SDL_SCANCODE_7,
38 /*0x09*/ SDL_SCANCODE_8,
39 /*0x0a*/ SDL_SCANCODE_9,
40 /*0x0b*/ SDL_SCANCODE_0,
41 /*0x0c*/ SDL_SCANCODE_MINUS,
42 /*0x0d*/ SDL_SCANCODE_EQUALS,
43 /*0x0e*/ SDL_SCANCODE_BACKSPACE,
44 /*0x0f*/ SDL_SCANCODE_TAB,
45 /*0x10*/ SDL_SCANCODE_Q,
46 /*0x11*/ SDL_SCANCODE_W,
47 /*0x12*/ SDL_SCANCODE_E,
48 /*0x13*/ SDL_SCANCODE_R,
49 /*0x14*/ SDL_SCANCODE_T,
50 /*0x15*/ SDL_SCANCODE_Y,
51 /*0x16*/ SDL_SCANCODE_U,
52 /*0x17*/ SDL_SCANCODE_I,
53 /*0x18*/ SDL_SCANCODE_O,
54 /*0x19*/ SDL_SCANCODE_P,
55 /*0x1a*/ SDL_SCANCODE_LEFTBRACKET,
56 /*0x1b*/ SDL_SCANCODE_RIGHTBRACKET,
57 /*0x1c*/ SDL_SCANCODE_RETURN,
58 /*0x1d*/ SDL_SCANCODE_LCTRL,
59 /*0x1e*/ SDL_SCANCODE_A,
60 /*0x1f*/ SDL_SCANCODE_S,
61 /*0x20*/ SDL_SCANCODE_D,
62 /*0x21*/ SDL_SCANCODE_F,
63 /*0x22*/ SDL_SCANCODE_G,
64 /*0x23*/ SDL_SCANCODE_H,
65 /*0x24*/ SDL_SCANCODE_J,
66 /*0x25*/ SDL_SCANCODE_K,
67 /*0x26*/ SDL_SCANCODE_L,
68 /*0x27*/ SDL_SCANCODE_SEMICOLON,
69 /*0x28*/ SDL_SCANCODE_APOSTROPHE,
70 /*0x29*/ SDL_SCANCODE_GRAVE,
71 /*0x2a*/ SDL_SCANCODE_LSHIFT,
72 /*0x2b*/ SDL_SCANCODE_BACKSLASH,
73 /*0x2c*/ SDL_SCANCODE_Z,
74 /*0x2d*/ SDL_SCANCODE_X,
75 /*0x2e*/ SDL_SCANCODE_C,
76 /*0x2f*/ SDL_SCANCODE_V,
77 /*0x30*/ SDL_SCANCODE_B,
78 /*0x31*/ SDL_SCANCODE_N,
79 /*0x32*/ SDL_SCANCODE_M,
80 /*0x33*/ SDL_SCANCODE_COMMA,
81 /*0x34*/ SDL_SCANCODE_PERIOD,
82 /*0x35*/ SDL_SCANCODE_SLASH,
83 /*0x36*/ SDL_SCANCODE_RSHIFT,
84 /*0x37*/ SDL_SCANCODE_KP_MULTIPLY,
85 /*0x38*/ SDL_SCANCODE_LALT,
86 /*0x39*/ SDL_SCANCODE_SPACE,
87 /*0x3a*/ SDL_SCANCODE_CAPSLOCK,
88 /*0x3b*/ SDL_SCANCODE_F1,
89 /*0x3c*/ SDL_SCANCODE_F2,
90 /*0x3d*/ SDL_SCANCODE_F3,
91 /*0x3e*/ SDL_SCANCODE_F4,
92 /*0x3f*/ SDL_SCANCODE_F5,
93 /*0x40*/ SDL_SCANCODE_F6,
94 /*0x41*/ SDL_SCANCODE_F7,
95 /*0x42*/ SDL_SCANCODE_F8,
96 /*0x43*/ SDL_SCANCODE_F9,
97 /*0x44*/ SDL_SCANCODE_F10,
98 /*0x45*/ SDL_SCANCODE_NUMLOCKCLEAR,
99 /*0x46*/ SDL_SCANCODE_SCROLLLOCK,
100 /*0x47*/ SDL_SCANCODE_KP_7,
101 /*0x48*/ SDL_SCANCODE_KP_8,
102 /*0x49*/ SDL_SCANCODE_KP_9,
103 /*0x4a*/ SDL_SCANCODE_KP_MINUS,
104 /*0x4b*/ SDL_SCANCODE_KP_4,
105 /*0x4c*/ SDL_SCANCODE_KP_5,
106 /*0x4d*/ SDL_SCANCODE_KP_6,
107 /*0x4e*/ SDL_SCANCODE_KP_PLUS,
108 /*0x4f*/ SDL_SCANCODE_KP_1,
109 /*0x50*/ SDL_SCANCODE_KP_2,
110 /*0x51*/ SDL_SCANCODE_KP_3,
111 /*0x52*/ SDL_SCANCODE_KP_0,
112 /*0x53*/ SDL_SCANCODE_KP_PERIOD,
113 /*0x54*/ SDL_SCANCODE_UNKNOWN,
114 /*0x55*/ SDL_SCANCODE_UNKNOWN,
115 /*0x56*/ SDL_SCANCODE_NONUSBACKSLASH,
116 /*0x57*/ SDL_SCANCODE_F11,
117 /*0x58*/ SDL_SCANCODE_F12,
118 /*0x59*/ SDL_SCANCODE_KP_EQUALS,
119 /*0x5a*/ SDL_SCANCODE_UNKNOWN,
120 /*0x5b*/ SDL_SCANCODE_UNKNOWN,
121 /*0x5c*/ SDL_SCANCODE_INTERNATIONAL6,
122 /*0x5d*/ SDL_SCANCODE_UNKNOWN,
123 /*0x5e*/ SDL_SCANCODE_UNKNOWN,
124 /*0x5f*/ SDL_SCANCODE_UNKNOWN,
125 /*0x60*/ SDL_SCANCODE_UNKNOWN,
126 /*0x61*/ SDL_SCANCODE_UNKNOWN,
127 /*0x62*/ SDL_SCANCODE_UNKNOWN,
128 /*0x63*/ SDL_SCANCODE_UNKNOWN,
129 /*0x64*/ SDL_SCANCODE_F13,
130 /*0x65*/ SDL_SCANCODE_F14,
131 /*0x66*/ SDL_SCANCODE_F15,
132 /*0x67*/ SDL_SCANCODE_F16,
133 /*0x68*/ SDL_SCANCODE_F17,
134 /*0x69*/ SDL_SCANCODE_F18,
135 /*0x6a*/ SDL_SCANCODE_F19,
136 /*0x6b*/ SDL_SCANCODE_F20,
137 /*0x6c*/ SDL_SCANCODE_F21,
138 /*0x6d*/ SDL_SCANCODE_F22,
139 /*0x6e*/ SDL_SCANCODE_F23,
140 /*0x6f*/ SDL_SCANCODE_UNKNOWN,
141 /*0x70*/ SDL_SCANCODE_INTERNATIONAL2,
142 /*0x71*/ SDL_SCANCODE_LANG2,
143 /*0x72*/ SDL_SCANCODE_LANG1,
144 /*0x73*/ SDL_SCANCODE_INTERNATIONAL1,
145 /*0x74*/ SDL_SCANCODE_UNKNOWN,
146 /*0x75*/ SDL_SCANCODE_UNKNOWN,
147 /*0x76*/ SDL_SCANCODE_F24,
148 /*0x77*/ SDL_SCANCODE_LANG4,
149 /*0x78*/ SDL_SCANCODE_LANG3,
150 /*0x79*/ SDL_SCANCODE_INTERNATIONAL4,
151 /*0x7a*/ SDL_SCANCODE_UNKNOWN,
152 /*0x7b*/ SDL_SCANCODE_INTERNATIONAL5,
153 /*0x7c*/ SDL_SCANCODE_UNKNOWN,
154 /*0x7d*/ SDL_SCANCODE_INTERNATIONAL3,
155 /*0x7e*/ SDL_SCANCODE_KP_COMMA,
156 /*0x7f*/ SDL_SCANCODE_UNKNOWN,
157 /*0xe000*/ SDL_SCANCODE_UNKNOWN,
158 /*0xe001*/ SDL_SCANCODE_UNKNOWN,
159 /*0xe002*/ SDL_SCANCODE_UNKNOWN,
160 /*0xe003*/ SDL_SCANCODE_UNKNOWN,
161 /*0xe004*/ SDL_SCANCODE_UNKNOWN,
162 /*0xe005*/ SDL_SCANCODE_UNKNOWN,
163 /*0xe006*/ SDL_SCANCODE_UNKNOWN,
164 /*0xe007*/ SDL_SCANCODE_UNKNOWN,
165 /*0xe008*/ SDL_SCANCODE_UNKNOWN,
166 /*0xe009*/ SDL_SCANCODE_UNKNOWN,
167 /*0xe00a*/ SDL_SCANCODE_PASTE,
168 /*0xe00b*/ SDL_SCANCODE_UNKNOWN,
169 /*0xe00c*/ SDL_SCANCODE_UNKNOWN,
170 /*0xe00d*/ SDL_SCANCODE_UNKNOWN,
171 /*0xe00e*/ SDL_SCANCODE_UNKNOWN,
172 /*0xe00f*/ SDL_SCANCODE_UNKNOWN,
173 /*0xe010*/ SDL_SCANCODE_MEDIA_PREVIOUS_TRACK,
174 /*0xe011*/ SDL_SCANCODE_UNKNOWN,
175 /*0xe012*/ SDL_SCANCODE_UNKNOWN,
176 /*0xe013*/ SDL_SCANCODE_UNKNOWN,
177 /*0xe014*/ SDL_SCANCODE_UNKNOWN,
178 /*0xe015*/ SDL_SCANCODE_UNKNOWN,
179 /*0xe016*/ SDL_SCANCODE_UNKNOWN,
180 /*0xe017*/ SDL_SCANCODE_CUT,
181 /*0xe018*/ SDL_SCANCODE_COPY,
182 /*0xe019*/ SDL_SCANCODE_MEDIA_NEXT_TRACK,
183 /*0xe01a*/ SDL_SCANCODE_UNKNOWN,
184 /*0xe01b*/ SDL_SCANCODE_UNKNOWN,
185 /*0xe01c*/ SDL_SCANCODE_KP_ENTER,
186 /*0xe01d*/ SDL_SCANCODE_RCTRL,
187 /*0xe01e*/ SDL_SCANCODE_UNKNOWN,
188 /*0xe01f*/ SDL_SCANCODE_UNKNOWN,
189 /*0xe020*/ SDL_SCANCODE_MUTE,
190 /*0xe021*/ SDL_SCANCODE_UNKNOWN, // LaunchApp2
191 /*0xe022*/ SDL_SCANCODE_MEDIA_PLAY_PAUSE,
192 /*0xe023*/ SDL_SCANCODE_UNKNOWN,
193 /*0xe024*/ SDL_SCANCODE_MEDIA_STOP,
194 /*0xe025*/ SDL_SCANCODE_UNKNOWN,
195 /*0xe026*/ SDL_SCANCODE_UNKNOWN,
196 /*0xe027*/ SDL_SCANCODE_UNKNOWN,
197 /*0xe028*/ SDL_SCANCODE_UNKNOWN,
198 /*0xe029*/ SDL_SCANCODE_UNKNOWN,
199 /*0xe02a*/ SDL_SCANCODE_UNKNOWN,
200 /*0xe02b*/ SDL_SCANCODE_UNKNOWN,
201 /*0xe02c*/ SDL_SCANCODE_MEDIA_EJECT,
202 /*0xe02d*/ SDL_SCANCODE_UNKNOWN,
203 /*0xe02e*/ SDL_SCANCODE_VOLUMEDOWN,
204 /*0xe02f*/ SDL_SCANCODE_UNKNOWN,
205 /*0xe030*/ SDL_SCANCODE_VOLUMEUP,
206 /*0xe031*/ SDL_SCANCODE_UNKNOWN,
207 /*0xe032*/ SDL_SCANCODE_AC_HOME,
208 /*0xe033*/ SDL_SCANCODE_UNKNOWN,
209 /*0xe034*/ SDL_SCANCODE_UNKNOWN,
210 /*0xe035*/ SDL_SCANCODE_KP_DIVIDE,
211 /*0xe036*/ SDL_SCANCODE_UNKNOWN,
212 /*0xe037*/ SDL_SCANCODE_PRINTSCREEN,
213 /*0xe038*/ SDL_SCANCODE_RALT,
214 /*0xe039*/ SDL_SCANCODE_UNKNOWN,
215 /*0xe03a*/ SDL_SCANCODE_UNKNOWN,
216 /*0xe03b*/ SDL_SCANCODE_HELP,
217 /*0xe03c*/ SDL_SCANCODE_UNKNOWN,
218 /*0xe03d*/ SDL_SCANCODE_UNKNOWN,
219 /*0xe03e*/ SDL_SCANCODE_UNKNOWN,
220 /*0xe03f*/ SDL_SCANCODE_UNKNOWN,
221 /*0xe040*/ SDL_SCANCODE_UNKNOWN,
222 /*0xe041*/ SDL_SCANCODE_UNKNOWN,
223 /*0xe042*/ SDL_SCANCODE_UNKNOWN,
224 /*0xe043*/ SDL_SCANCODE_UNKNOWN,
225 /*0xe044*/ SDL_SCANCODE_UNKNOWN,
226 /*0xe045*/ SDL_SCANCODE_NUMLOCKCLEAR,
227 /*0xe046*/ SDL_SCANCODE_PAUSE,
228 /*0xe047*/ SDL_SCANCODE_HOME,
229 /*0xe048*/ SDL_SCANCODE_UP,
230 /*0xe049*/ SDL_SCANCODE_PAGEUP,
231 /*0xe04a*/ SDL_SCANCODE_UNKNOWN,
232 /*0xe04b*/ SDL_SCANCODE_LEFT,
233 /*0xe04c*/ SDL_SCANCODE_UNKNOWN,
234 /*0xe04d*/ SDL_SCANCODE_RIGHT,
235 /*0xe04e*/ SDL_SCANCODE_UNKNOWN,
236 /*0xe04f*/ SDL_SCANCODE_END,
237 /*0xe050*/ SDL_SCANCODE_DOWN,
238 /*0xe051*/ SDL_SCANCODE_PAGEDOWN,
239 /*0xe052*/ SDL_SCANCODE_INSERT,
240 /*0xe053*/ SDL_SCANCODE_DELETE,
241 /*0xe054*/ SDL_SCANCODE_UNKNOWN,
242 /*0xe055*/ SDL_SCANCODE_UNKNOWN,
243 /*0xe056*/ SDL_SCANCODE_UNKNOWN,
244 /*0xe057*/ SDL_SCANCODE_UNKNOWN,
245 /*0xe058*/ SDL_SCANCODE_UNKNOWN,
246 /*0xe059*/ SDL_SCANCODE_UNKNOWN,
247 /*0xe05a*/ SDL_SCANCODE_UNKNOWN,
248 /*0xe05b*/ SDL_SCANCODE_LGUI,
249 /*0xe05c*/ SDL_SCANCODE_RGUI,
250 /*0xe05d*/ SDL_SCANCODE_APPLICATION,
251 /*0xe05e*/ SDL_SCANCODE_POWER,
252 /*0xe05f*/ SDL_SCANCODE_SLEEP,
253 /*0xe060*/ SDL_SCANCODE_UNKNOWN,
254 /*0xe061*/ SDL_SCANCODE_UNKNOWN,
255 /*0xe062*/ SDL_SCANCODE_UNKNOWN,
256 /*0xe063*/ SDL_SCANCODE_UNKNOWN,
257 /*0xe064*/ SDL_SCANCODE_UNKNOWN,
258 /*0xe065*/ SDL_SCANCODE_AC_SEARCH,
259 /*0xe066*/ SDL_SCANCODE_AC_BOOKMARKS,
260 /*0xe067*/ SDL_SCANCODE_AC_REFRESH,
261 /*0xe068*/ SDL_SCANCODE_AC_STOP,
262 /*0xe069*/ SDL_SCANCODE_AC_FORWARD,
263 /*0xe06a*/ SDL_SCANCODE_AC_BACK,
264 /*0xe06b*/ SDL_SCANCODE_UNKNOWN, // LaunchApp1
265 /*0xe06c*/ SDL_SCANCODE_UNKNOWN, // LaunchMail
266 /*0xe06d*/ SDL_SCANCODE_MEDIA_SELECT,
267 /*0xe06e*/ SDL_SCANCODE_UNKNOWN,
268 /*0xe06f*/ SDL_SCANCODE_UNKNOWN,
269 /*0xe070*/ SDL_SCANCODE_UNKNOWN,
270 /*0xe071*/ SDL_SCANCODE_UNKNOWN,
271 /*0xe072*/ SDL_SCANCODE_UNKNOWN,
272 /*0xe073*/ SDL_SCANCODE_UNKNOWN,
273 /*0xe074*/ SDL_SCANCODE_UNKNOWN,
274 /*0xe075*/ SDL_SCANCODE_UNKNOWN,
275 /*0xe076*/ SDL_SCANCODE_UNKNOWN,
276 /*0xe077*/ SDL_SCANCODE_UNKNOWN,
277 /*0xe078*/ SDL_SCANCODE_UNKNOWN,
278 /*0xe079*/ SDL_SCANCODE_UNKNOWN,
279 /*0xe07a*/ SDL_SCANCODE_UNKNOWN,
280 /*0xe07b*/ SDL_SCANCODE_UNKNOWN,
281 /*0xe07c*/ SDL_SCANCODE_UNKNOWN,
282 /*0xe07d*/ SDL_SCANCODE_UNKNOWN,
283 /*0xe07e*/ SDL_SCANCODE_UNKNOWN,
284 /*0xe07f*/ SDL_SCANCODE_UNKNOWN
285};
286/* *INDENT-ON* */ // clang-format on
diff --git a/contrib/SDL-3.2.8/src/events/scancodes_xfree86.h b/contrib/SDL-3.2.8/src/events/scancodes_xfree86.h
new file mode 100644
index 0000000..5e51bb1
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/scancodes_xfree86.h
@@ -0,0 +1,520 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef scancodes_xfree86_h_
24#define scancodes_xfree86_h_
25
26/* XFree86 key code to SDL scancode mapping table
27 Sources:
28 - atKeyNames.h from XFree86 source code
29*/
30/* *INDENT-OFF* */ // clang-format off
31static const SDL_Scancode xfree86_scancode_table[] = {
32 /* 0 */ SDL_SCANCODE_UNKNOWN,
33 /* 1 */ SDL_SCANCODE_ESCAPE,
34 /* 2 */ SDL_SCANCODE_1,
35 /* 3 */ SDL_SCANCODE_2,
36 /* 4 */ SDL_SCANCODE_3,
37 /* 5 */ SDL_SCANCODE_4,
38 /* 6 */ SDL_SCANCODE_5,
39 /* 7 */ SDL_SCANCODE_6,
40 /* 8 */ SDL_SCANCODE_7,
41 /* 9 */ SDL_SCANCODE_8,
42 /* 10 */ SDL_SCANCODE_9,
43 /* 11 */ SDL_SCANCODE_0,
44 /* 12 */ SDL_SCANCODE_MINUS,
45 /* 13 */ SDL_SCANCODE_EQUALS,
46 /* 14 */ SDL_SCANCODE_BACKSPACE,
47 /* 15 */ SDL_SCANCODE_TAB,
48 /* 16 */ SDL_SCANCODE_Q,
49 /* 17 */ SDL_SCANCODE_W,
50 /* 18 */ SDL_SCANCODE_E,
51 /* 19 */ SDL_SCANCODE_R,
52 /* 20 */ SDL_SCANCODE_T,
53 /* 21 */ SDL_SCANCODE_Y,
54 /* 22 */ SDL_SCANCODE_U,
55 /* 23 */ SDL_SCANCODE_I,
56 /* 24 */ SDL_SCANCODE_O,
57 /* 25 */ SDL_SCANCODE_P,
58 /* 26 */ SDL_SCANCODE_LEFTBRACKET,
59 /* 27 */ SDL_SCANCODE_RIGHTBRACKET,
60 /* 28 */ SDL_SCANCODE_RETURN,
61 /* 29 */ SDL_SCANCODE_LCTRL,
62 /* 30 */ SDL_SCANCODE_A,
63 /* 31 */ SDL_SCANCODE_S,
64 /* 32 */ SDL_SCANCODE_D,
65 /* 33 */ SDL_SCANCODE_F,
66 /* 34 */ SDL_SCANCODE_G,
67 /* 35 */ SDL_SCANCODE_H,
68 /* 36 */ SDL_SCANCODE_J,
69 /* 37 */ SDL_SCANCODE_K,
70 /* 38 */ SDL_SCANCODE_L,
71 /* 39 */ SDL_SCANCODE_SEMICOLON,
72 /* 40 */ SDL_SCANCODE_APOSTROPHE,
73 /* 41 */ SDL_SCANCODE_GRAVE,
74 /* 42 */ SDL_SCANCODE_LSHIFT,
75 /* 43 */ SDL_SCANCODE_BACKSLASH,
76 /* 44 */ SDL_SCANCODE_Z,
77 /* 45 */ SDL_SCANCODE_X,
78 /* 46 */ SDL_SCANCODE_C,
79 /* 47 */ SDL_SCANCODE_V,
80 /* 48 */ SDL_SCANCODE_B,
81 /* 49 */ SDL_SCANCODE_N,
82 /* 50 */ SDL_SCANCODE_M,
83 /* 51 */ SDL_SCANCODE_COMMA,
84 /* 52 */ SDL_SCANCODE_PERIOD,
85 /* 53 */ SDL_SCANCODE_SLASH,
86 /* 54 */ SDL_SCANCODE_RSHIFT,
87 /* 55 */ SDL_SCANCODE_KP_MULTIPLY,
88 /* 56 */ SDL_SCANCODE_LALT,
89 /* 57 */ SDL_SCANCODE_SPACE,
90 /* 58 */ SDL_SCANCODE_CAPSLOCK,
91 /* 59 */ SDL_SCANCODE_F1,
92 /* 60 */ SDL_SCANCODE_F2,
93 /* 61 */ SDL_SCANCODE_F3,
94 /* 62 */ SDL_SCANCODE_F4,
95 /* 63 */ SDL_SCANCODE_F5,
96 /* 64 */ SDL_SCANCODE_F6,
97 /* 65 */ SDL_SCANCODE_F7,
98 /* 66 */ SDL_SCANCODE_F8,
99 /* 67 */ SDL_SCANCODE_F9,
100 /* 68 */ SDL_SCANCODE_F10,
101 /* 69 */ SDL_SCANCODE_NUMLOCKCLEAR,
102 /* 70 */ SDL_SCANCODE_SCROLLLOCK,
103 /* 71 */ SDL_SCANCODE_KP_7,
104 /* 72 */ SDL_SCANCODE_KP_8,
105 /* 73 */ SDL_SCANCODE_KP_9,
106 /* 74 */ SDL_SCANCODE_KP_MINUS,
107 /* 75 */ SDL_SCANCODE_KP_4,
108 /* 76 */ SDL_SCANCODE_KP_5,
109 /* 77 */ SDL_SCANCODE_KP_6,
110 /* 78 */ SDL_SCANCODE_KP_PLUS,
111 /* 79 */ SDL_SCANCODE_KP_1,
112 /* 80 */ SDL_SCANCODE_KP_2,
113 /* 81 */ SDL_SCANCODE_KP_3,
114 /* 82 */ SDL_SCANCODE_KP_0,
115 /* 83 */ SDL_SCANCODE_KP_PERIOD,
116 /* 84 */ SDL_SCANCODE_SYSREQ,
117 /* 85 */ SDL_SCANCODE_MODE,
118 /* 86 */ SDL_SCANCODE_NONUSBACKSLASH,
119 /* 87 */ SDL_SCANCODE_F11,
120 /* 88 */ SDL_SCANCODE_F12,
121 /* 89 */ SDL_SCANCODE_HOME,
122 /* 90 */ SDL_SCANCODE_UP,
123 /* 91 */ SDL_SCANCODE_PAGEUP,
124 /* 92 */ SDL_SCANCODE_LEFT,
125 /* 93 */ SDL_SCANCODE_UNKNOWN, // on PowerBook G4 / KEY_Begin
126 /* 94 */ SDL_SCANCODE_RIGHT,
127 /* 95 */ SDL_SCANCODE_END,
128 /* 96 */ SDL_SCANCODE_DOWN,
129 /* 97 */ SDL_SCANCODE_PAGEDOWN,
130 /* 98 */ SDL_SCANCODE_INSERT,
131 /* 99 */ SDL_SCANCODE_DELETE,
132 /* 100 */ SDL_SCANCODE_KP_ENTER,
133 /* 101 */ SDL_SCANCODE_RCTRL,
134 /* 102 */ SDL_SCANCODE_PAUSE,
135 /* 103 */ SDL_SCANCODE_PRINTSCREEN,
136 /* 104 */ SDL_SCANCODE_KP_DIVIDE,
137 /* 105 */ SDL_SCANCODE_RALT,
138 /* 106 */ SDL_SCANCODE_UNKNOWN, // BREAK
139 /* 107 */ SDL_SCANCODE_LGUI,
140 /* 108 */ SDL_SCANCODE_RGUI,
141 /* 109 */ SDL_SCANCODE_APPLICATION,
142 /* 110 */ SDL_SCANCODE_F13,
143 /* 111 */ SDL_SCANCODE_F14,
144 /* 112 */ SDL_SCANCODE_F15,
145 /* 113 */ SDL_SCANCODE_F16,
146 /* 114 */ SDL_SCANCODE_F17,
147 /* 115 */ SDL_SCANCODE_INTERNATIONAL1, // \_
148 /* 116 */ SDL_SCANCODE_UNKNOWN, /* is translated to XK_ISO_Level3_Shift by my X server, but I have no keyboard that generates this code, so I don't know what the correct SDL_SCANCODE_* for it is */
149 /* 117 */ SDL_SCANCODE_UNKNOWN,
150 /* 118 */ SDL_SCANCODE_KP_EQUALS,
151 /* 119 */ SDL_SCANCODE_UNKNOWN,
152 /* 120 */ SDL_SCANCODE_UNKNOWN,
153 /* 121 */ SDL_SCANCODE_INTERNATIONAL4, // Henkan_Mode
154 /* 122 */ SDL_SCANCODE_UNKNOWN,
155 /* 123 */ SDL_SCANCODE_INTERNATIONAL5, // Muhenkan
156 /* 124 */ SDL_SCANCODE_UNKNOWN,
157 /* 125 */ SDL_SCANCODE_INTERNATIONAL3, // Yen
158 /* 126 */ SDL_SCANCODE_UNKNOWN,
159 /* 127 */ SDL_SCANCODE_UNKNOWN,
160 /* 128 */ SDL_SCANCODE_UNKNOWN,
161 /* 129 */ SDL_SCANCODE_UNKNOWN,
162 /* 130 */ SDL_SCANCODE_UNKNOWN,
163 /* 131 */ SDL_SCANCODE_UNKNOWN,
164 /* 132 */ SDL_SCANCODE_POWER,
165 /* 133 */ SDL_SCANCODE_MUTE,
166 /* 134 */ SDL_SCANCODE_VOLUMEDOWN,
167 /* 135 */ SDL_SCANCODE_VOLUMEUP,
168 /* 136 */ SDL_SCANCODE_HELP,
169 /* 137 */ SDL_SCANCODE_STOP,
170 /* 138 */ SDL_SCANCODE_AGAIN,
171 /* 139 */ SDL_SCANCODE_UNKNOWN, // PROPS
172 /* 140 */ SDL_SCANCODE_UNDO,
173 /* 141 */ SDL_SCANCODE_UNKNOWN, // FRONT
174 /* 142 */ SDL_SCANCODE_COPY,
175 /* 143 */ SDL_SCANCODE_UNKNOWN, // OPEN
176 /* 144 */ SDL_SCANCODE_PASTE,
177 /* 145 */ SDL_SCANCODE_FIND,
178 /* 146 */ SDL_SCANCODE_CUT,
179};
180
181// This is largely identical to the Linux keycode mapping
182static const SDL_Scancode xfree86_scancode_table2[] = {
183 /* 0, 0x000 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
184 /* 1, 0x001 */ SDL_SCANCODE_ESCAPE, // Escape
185 /* 2, 0x002 */ SDL_SCANCODE_1, // 1
186 /* 3, 0x003 */ SDL_SCANCODE_2, // 2
187 /* 4, 0x004 */ SDL_SCANCODE_3, // 3
188 /* 5, 0x005 */ SDL_SCANCODE_4, // 4
189 /* 6, 0x006 */ SDL_SCANCODE_5, // 5
190 /* 7, 0x007 */ SDL_SCANCODE_6, // 6
191 /* 8, 0x008 */ SDL_SCANCODE_7, // 7
192 /* 9, 0x009 */ SDL_SCANCODE_8, // 8
193 /* 10, 0x00a */ SDL_SCANCODE_9, // 9
194 /* 11, 0x00b */ SDL_SCANCODE_0, // 0
195 /* 12, 0x00c */ SDL_SCANCODE_MINUS, // minus
196 /* 13, 0x00d */ SDL_SCANCODE_EQUALS, // equal
197 /* 14, 0x00e */ SDL_SCANCODE_BACKSPACE, // BackSpace
198 /* 15, 0x00f */ SDL_SCANCODE_TAB, // Tab
199 /* 16, 0x010 */ SDL_SCANCODE_Q, // q
200 /* 17, 0x011 */ SDL_SCANCODE_W, // w
201 /* 18, 0x012 */ SDL_SCANCODE_E, // e
202 /* 19, 0x013 */ SDL_SCANCODE_R, // r
203 /* 20, 0x014 */ SDL_SCANCODE_T, // t
204 /* 21, 0x015 */ SDL_SCANCODE_Y, // y
205 /* 22, 0x016 */ SDL_SCANCODE_U, // u
206 /* 23, 0x017 */ SDL_SCANCODE_I, // i
207 /* 24, 0x018 */ SDL_SCANCODE_O, // o
208 /* 25, 0x019 */ SDL_SCANCODE_P, // p
209 /* 26, 0x01a */ SDL_SCANCODE_LEFTBRACKET, // bracketleft
210 /* 27, 0x01b */ SDL_SCANCODE_RIGHTBRACKET, // bracketright
211 /* 28, 0x01c */ SDL_SCANCODE_RETURN, // Return
212 /* 29, 0x01d */ SDL_SCANCODE_LCTRL, // Control_L
213 /* 30, 0x01e */ SDL_SCANCODE_A, // a
214 /* 31, 0x01f */ SDL_SCANCODE_S, // s
215 /* 32, 0x020 */ SDL_SCANCODE_D, // d
216 /* 33, 0x021 */ SDL_SCANCODE_F, // f
217 /* 34, 0x022 */ SDL_SCANCODE_G, // g
218 /* 35, 0x023 */ SDL_SCANCODE_H, // h
219 /* 36, 0x024 */ SDL_SCANCODE_J, // j
220 /* 37, 0x025 */ SDL_SCANCODE_K, // k
221 /* 38, 0x026 */ SDL_SCANCODE_L, // l
222 /* 39, 0x027 */ SDL_SCANCODE_SEMICOLON, // semicolon
223 /* 40, 0x028 */ SDL_SCANCODE_APOSTROPHE, // apostrophe
224 /* 41, 0x029 */ SDL_SCANCODE_GRAVE, // grave
225 /* 42, 0x02a */ SDL_SCANCODE_LSHIFT, // Shift_L
226 /* 43, 0x02b */ SDL_SCANCODE_BACKSLASH, // backslash
227 /* 44, 0x02c */ SDL_SCANCODE_Z, // z
228 /* 45, 0x02d */ SDL_SCANCODE_X, // x
229 /* 46, 0x02e */ SDL_SCANCODE_C, // c
230 /* 47, 0x02f */ SDL_SCANCODE_V, // v
231 /* 48, 0x030 */ SDL_SCANCODE_B, // b
232 /* 49, 0x031 */ SDL_SCANCODE_N, // n
233 /* 50, 0x032 */ SDL_SCANCODE_M, // m
234 /* 51, 0x033 */ SDL_SCANCODE_COMMA, // comma
235 /* 52, 0x034 */ SDL_SCANCODE_PERIOD, // period
236 /* 53, 0x035 */ SDL_SCANCODE_SLASH, // slash
237 /* 54, 0x036 */ SDL_SCANCODE_RSHIFT, // Shift_R
238 /* 55, 0x037 */ SDL_SCANCODE_KP_MULTIPLY, // KP_Multiply
239 /* 56, 0x038 */ SDL_SCANCODE_LALT, // Alt_L
240 /* 57, 0x039 */ SDL_SCANCODE_SPACE, // space
241 /* 58, 0x03a */ SDL_SCANCODE_CAPSLOCK, // Caps_Lock
242 /* 59, 0x03b */ SDL_SCANCODE_F1, // F1
243 /* 60, 0x03c */ SDL_SCANCODE_F2, // F2
244 /* 61, 0x03d */ SDL_SCANCODE_F3, // F3
245 /* 62, 0x03e */ SDL_SCANCODE_F4, // F4
246 /* 63, 0x03f */ SDL_SCANCODE_F5, // F5
247 /* 64, 0x040 */ SDL_SCANCODE_F6, // F6
248 /* 65, 0x041 */ SDL_SCANCODE_F7, // F7
249 /* 66, 0x042 */ SDL_SCANCODE_F8, // F8
250 /* 67, 0x043 */ SDL_SCANCODE_F9, // F9
251 /* 68, 0x044 */ SDL_SCANCODE_F10, // F10
252 /* 69, 0x045 */ SDL_SCANCODE_NUMLOCKCLEAR, // Num_Lock
253 /* 70, 0x046 */ SDL_SCANCODE_SCROLLLOCK, // Scroll_Lock
254 /* 71, 0x047 */ SDL_SCANCODE_KP_7, // KP_Home
255 /* 72, 0x048 */ SDL_SCANCODE_KP_8, // KP_Up
256 /* 73, 0x049 */ SDL_SCANCODE_KP_9, // KP_Prior
257 /* 74, 0x04a */ SDL_SCANCODE_KP_MINUS, // KP_Subtract
258 /* 75, 0x04b */ SDL_SCANCODE_KP_4, // KP_Left
259 /* 76, 0x04c */ SDL_SCANCODE_KP_5, // KP_Begin
260 /* 77, 0x04d */ SDL_SCANCODE_KP_6, // KP_Right
261 /* 78, 0x04e */ SDL_SCANCODE_KP_PLUS, // KP_Add
262 /* 79, 0x04f */ SDL_SCANCODE_KP_1, // KP_End
263 /* 80, 0x050 */ SDL_SCANCODE_KP_2, // KP_Down
264 /* 81, 0x051 */ SDL_SCANCODE_KP_3, // KP_Next
265 /* 82, 0x052 */ SDL_SCANCODE_KP_0, // KP_Insert
266 /* 83, 0x053 */ SDL_SCANCODE_KP_PERIOD, // KP_Delete
267 /* 84, 0x054 */ SDL_SCANCODE_RALT, // ISO_Level3_Shift
268 /* 85, 0x055 */ SDL_SCANCODE_MODE, // ????
269 /* 86, 0x056 */ SDL_SCANCODE_NONUSBACKSLASH, // less
270 /* 87, 0x057 */ SDL_SCANCODE_F11, // F11
271 /* 88, 0x058 */ SDL_SCANCODE_F12, // F12
272 /* 89, 0x059 */ SDL_SCANCODE_INTERNATIONAL1, // \_
273 /* 90, 0x05a */ SDL_SCANCODE_LANG3, // Katakana
274 /* 91, 0x05b */ SDL_SCANCODE_LANG4, // Hiragana
275 /* 92, 0x05c */ SDL_SCANCODE_INTERNATIONAL4, // Henkan_Mode
276 /* 93, 0x05d */ SDL_SCANCODE_INTERNATIONAL2, // Hiragana_Katakana
277 /* 94, 0x05e */ SDL_SCANCODE_INTERNATIONAL5, // Muhenkan
278 /* 95, 0x05f */ SDL_SCANCODE_UNKNOWN, // NoSymbol
279 /* 96, 0x060 */ SDL_SCANCODE_KP_ENTER, // KP_Enter
280 /* 97, 0x061 */ SDL_SCANCODE_RCTRL, // Control_R
281 /* 98, 0x062 */ SDL_SCANCODE_KP_DIVIDE, // KP_Divide
282 /* 99, 0x063 */ SDL_SCANCODE_PRINTSCREEN, // Print
283 /* 100, 0x064 */ SDL_SCANCODE_RALT, // ISO_Level3_Shift, ALTGR, RALT
284 /* 101, 0x065 */ SDL_SCANCODE_UNKNOWN, // Linefeed
285 /* 102, 0x066 */ SDL_SCANCODE_HOME, // Home
286 /* 103, 0x067 */ SDL_SCANCODE_UP, // Up
287 /* 104, 0x068 */ SDL_SCANCODE_PAGEUP, // Prior
288 /* 105, 0x069 */ SDL_SCANCODE_LEFT, // Left
289 /* 106, 0x06a */ SDL_SCANCODE_RIGHT, // Right
290 /* 107, 0x06b */ SDL_SCANCODE_END, // End
291 /* 108, 0x06c */ SDL_SCANCODE_DOWN, // Down
292 /* 109, 0x06d */ SDL_SCANCODE_PAGEDOWN, // Next
293 /* 110, 0x06e */ SDL_SCANCODE_INSERT, // Insert
294 /* 111, 0x06f */ SDL_SCANCODE_DELETE, // Delete
295 /* 112, 0x070 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
296 /* 113, 0x071 */ SDL_SCANCODE_MUTE, // XF86AudioMute
297 /* 114, 0x072 */ SDL_SCANCODE_VOLUMEDOWN, // XF86AudioLowerVolume
298 /* 115, 0x073 */ SDL_SCANCODE_VOLUMEUP, // XF86AudioRaiseVolume
299 /* 116, 0x074 */ SDL_SCANCODE_POWER, // XF86PowerOff
300 /* 117, 0x075 */ SDL_SCANCODE_KP_EQUALS, // KP_Equal
301 /* 118, 0x076 */ SDL_SCANCODE_KP_PLUSMINUS, // plusminus
302 /* 119, 0x077 */ SDL_SCANCODE_PAUSE, // Pause
303 /* 120, 0x078 */ SDL_SCANCODE_UNKNOWN, // XF86LaunchA
304 /* 121, 0x079 */ SDL_SCANCODE_KP_PERIOD, // KP_Decimal
305 /* 122, 0x07a */ SDL_SCANCODE_LANG1, // Hangul
306 /* 123, 0x07b */ SDL_SCANCODE_LANG2, // Hangul_Hanja
307 /* 124, 0x07c */ SDL_SCANCODE_INTERNATIONAL3, // Yen
308 /* 125, 0x07d */ SDL_SCANCODE_LGUI, // Super_L
309 /* 126, 0x07e */ SDL_SCANCODE_RGUI, // Super_R
310 /* 127, 0x07f */ SDL_SCANCODE_APPLICATION, // Menu
311 /* 128, 0x080 */ SDL_SCANCODE_CANCEL, // Cancel
312 /* 129, 0x081 */ SDL_SCANCODE_AGAIN, // Redo
313 /* 130, 0x082 */ SDL_SCANCODE_UNKNOWN, // SunProps
314 /* 131, 0x083 */ SDL_SCANCODE_UNDO, // Undo
315 /* 132, 0x084 */ SDL_SCANCODE_UNKNOWN, // SunFront
316 /* 133, 0x085 */ SDL_SCANCODE_COPY, // XF86Copy
317 /* 134, 0x086 */ SDL_SCANCODE_UNKNOWN, // SunOpen, XF86Open
318 /* 135, 0x087 */ SDL_SCANCODE_PASTE, // XF86Paste
319 /* 136, 0x088 */ SDL_SCANCODE_FIND, // Find
320 /* 137, 0x089 */ SDL_SCANCODE_CUT, // XF86Cut
321 /* 138, 0x08a */ SDL_SCANCODE_HELP, // Help
322 /* 139, 0x08b */ SDL_SCANCODE_MENU, // XF86MenuKB
323 /* 140, 0x08c */ SDL_SCANCODE_UNKNOWN, // XF86Calculator
324 /* 141, 0x08d */ SDL_SCANCODE_UNKNOWN, // NoSymbol
325 /* 142, 0x08e */ SDL_SCANCODE_SLEEP, // XF86Sleep
326 /* 143, 0x08f */ SDL_SCANCODE_UNKNOWN, // XF86WakeUp
327 /* 144, 0x090 */ SDL_SCANCODE_UNKNOWN, // XF86Explorer
328 /* 145, 0x091 */ SDL_SCANCODE_UNKNOWN, // XF86Send
329 /* 146, 0x092 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
330 /* 147, 0x093 */ SDL_SCANCODE_UNKNOWN, // XF86Xfer
331 /* 148, 0x094 */ SDL_SCANCODE_UNKNOWN, // XF86Launch1
332 /* 149, 0x095 */ SDL_SCANCODE_UNKNOWN, // XF86Launch2
333 /* 150, 0x096 */ SDL_SCANCODE_UNKNOWN, // XF86WWW
334 /* 151, 0x097 */ SDL_SCANCODE_UNKNOWN, // XF86DOS
335 /* 152, 0x098 */ SDL_SCANCODE_UNKNOWN, // XF86ScreenSaver
336 /* 153, 0x099 */ SDL_SCANCODE_UNKNOWN, // XF86RotateWindows
337 /* 154, 0x09a */ SDL_SCANCODE_UNKNOWN, // XF86TaskPane
338 /* 155, 0x09b */ SDL_SCANCODE_UNKNOWN, // XF86Mail
339 /* 156, 0x09c */ SDL_SCANCODE_AC_BOOKMARKS, // XF86Favorites
340 /* 157, 0x09d */ SDL_SCANCODE_UNKNOWN, // XF86MyComputer
341 /* 158, 0x09e */ SDL_SCANCODE_AC_BACK, // XF86Back
342 /* 159, 0x09f */ SDL_SCANCODE_AC_FORWARD, // XF86Forward
343 /* 160, 0x0a0 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
344 /* 161, 0x0a1 */ SDL_SCANCODE_MEDIA_EJECT, // XF86Eject
345 /* 162, 0x0a2 */ SDL_SCANCODE_MEDIA_EJECT, // XF86Eject
346 /* 163, 0x0a3 */ SDL_SCANCODE_MEDIA_NEXT_TRACK, // XF86AudioNext
347 /* 164, 0x0a4 */ SDL_SCANCODE_MEDIA_PLAY_PAUSE, // XF86AudioPlay
348 /* 165, 0x0a5 */ SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, // XF86AudioPrev
349 /* 166, 0x0a6 */ SDL_SCANCODE_MEDIA_STOP, // XF86AudioStop
350 /* 167, 0x0a7 */ SDL_SCANCODE_MEDIA_RECORD, // XF86AudioRecord
351 /* 168, 0x0a8 */ SDL_SCANCODE_MEDIA_REWIND, // XF86AudioRewind
352 /* 169, 0x0a9 */ SDL_SCANCODE_UNKNOWN, // XF86Phone
353 /* 170, 0x0aa */ SDL_SCANCODE_UNKNOWN, // NoSymbol
354 /* 171, 0x0ab */ SDL_SCANCODE_F13, // XF86Tools
355 /* 172, 0x0ac */ SDL_SCANCODE_AC_HOME, // XF86HomePage
356 /* 173, 0x0ad */ SDL_SCANCODE_AC_REFRESH, // XF86Reload
357 /* 174, 0x0ae */ SDL_SCANCODE_UNKNOWN, // XF86Close
358 /* 175, 0x0af */ SDL_SCANCODE_UNKNOWN, // NoSymbol
359 /* 176, 0x0b0 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
360 /* 177, 0x0b1 */ SDL_SCANCODE_UNKNOWN, // XF86ScrollUp
361 /* 178, 0x0b2 */ SDL_SCANCODE_UNKNOWN, // XF86ScrollDown
362 /* 179, 0x0b3 */ SDL_SCANCODE_KP_LEFTPAREN, // parenleft
363 /* 180, 0x0b4 */ SDL_SCANCODE_KP_RIGHTPAREN, // parenright
364 /* 181, 0x0b5 */ SDL_SCANCODE_AC_NEW, // XF86New
365 /* 182, 0x0b6 */ SDL_SCANCODE_AGAIN, // Redo
366 /* 183, 0x0b7 */ SDL_SCANCODE_F13, // XF86Tools
367 /* 184, 0x0b8 */ SDL_SCANCODE_F14, // XF86Launch5
368 /* 185, 0x0b9 */ SDL_SCANCODE_F15, // XF86Launch6
369 /* 186, 0x0ba */ SDL_SCANCODE_F16, // XF86Launch7
370 /* 187, 0x0bb */ SDL_SCANCODE_F17, // XF86Launch8
371 /* 188, 0x0bc */ SDL_SCANCODE_F18, // XF86Launch9
372 /* 189, 0x0bd */ SDL_SCANCODE_F19, // NoSymbol
373 /* 190, 0x0be */ SDL_SCANCODE_F20, // XF86AudioMicMute
374 /* 191, 0x0bf */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadToggle
375 /* 192, 0x0c0 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOn
376 /* 193, 0x0c1 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOff
377 /* 194, 0x0c2 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
378 /* 195, 0x0c3 */ SDL_SCANCODE_MODE, // Mode_switch
379 /* 196, 0x0c4 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
380 /* 197, 0x0c5 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
381 /* 198, 0x0c6 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
382 /* 199, 0x0c7 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
383 /* 200, 0x0c8 */ SDL_SCANCODE_MEDIA_PLAY, // XF86AudioPlay
384 /* 201, 0x0c9 */ SDL_SCANCODE_MEDIA_PAUSE, // XF86AudioPause
385 /* 202, 0x0ca */ SDL_SCANCODE_UNKNOWN, // XF86Launch3
386 /* 203, 0x0cb */ SDL_SCANCODE_UNKNOWN, // XF86Launch4
387 /* 204, 0x0cc */ SDL_SCANCODE_UNKNOWN, // XF86LaunchB
388 /* 205, 0x0cd */ SDL_SCANCODE_UNKNOWN, // XF86Suspend
389 /* 206, 0x0ce */ SDL_SCANCODE_AC_CLOSE, // XF86Close
390 /* 207, 0x0cf */ SDL_SCANCODE_MEDIA_PLAY, // XF86AudioPlay
391 /* 208, 0x0d0 */ SDL_SCANCODE_MEDIA_FAST_FORWARD, // XF86AudioForward
392 /* 209, 0x0d1 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
393 /* 210, 0x0d2 */ SDL_SCANCODE_PRINTSCREEN, // Print
394 /* 211, 0x0d3 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
395 /* 212, 0x0d4 */ SDL_SCANCODE_UNKNOWN, // XF86WebCam
396 /* 213, 0x0d5 */ SDL_SCANCODE_UNKNOWN, // XF86AudioPreset
397 /* 214, 0x0d6 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
398 /* 215, 0x0d7 */ SDL_SCANCODE_UNKNOWN, // XF86Mail
399 /* 216, 0x0d8 */ SDL_SCANCODE_UNKNOWN, // XF86Messenger
400 /* 217, 0x0d9 */ SDL_SCANCODE_AC_SEARCH, // XF86Search
401 /* 218, 0x0da */ SDL_SCANCODE_UNKNOWN, // XF86Go
402 /* 219, 0x0db */ SDL_SCANCODE_UNKNOWN, // XF86Finance
403 /* 220, 0x0dc */ SDL_SCANCODE_UNKNOWN, // XF86Game
404 /* 221, 0x0dd */ SDL_SCANCODE_UNKNOWN, // XF86Shop
405 /* 222, 0x0de */ SDL_SCANCODE_UNKNOWN, // NoSymbol
406 /* 223, 0x0df */ SDL_SCANCODE_CANCEL, // Cancel
407 /* 224, 0x0e0 */ SDL_SCANCODE_UNKNOWN, // XF86MonBrightnessDown
408 /* 225, 0x0e1 */ SDL_SCANCODE_UNKNOWN, // XF86MonBrightnessUp
409 /* 226, 0x0e2 */ SDL_SCANCODE_MEDIA_SELECT, // XF86AudioMedia
410 /* 227, 0x0e3 */ SDL_SCANCODE_UNKNOWN, // XF86Display
411 /* 228, 0x0e4 */ SDL_SCANCODE_UNKNOWN, // XF86KbdLightOnOff
412 /* 229, 0x0e5 */ SDL_SCANCODE_UNKNOWN, // XF86KbdBrightnessDown
413 /* 230, 0x0e6 */ SDL_SCANCODE_UNKNOWN, // XF86KbdBrightnessUp
414 /* 231, 0x0e7 */ SDL_SCANCODE_UNKNOWN, // XF86Send
415 /* 232, 0x0e8 */ SDL_SCANCODE_UNKNOWN, // XF86Reply
416 /* 233, 0x0e9 */ SDL_SCANCODE_UNKNOWN, // XF86MailForward
417 /* 234, 0x0ea */ SDL_SCANCODE_UNKNOWN, // XF86Save
418 /* 235, 0x0eb */ SDL_SCANCODE_UNKNOWN, // XF86Documents
419 /* 236, 0x0ec */ SDL_SCANCODE_UNKNOWN, // XF86Battery
420 /* 237, 0x0ed */ SDL_SCANCODE_UNKNOWN, // XF86Bluetooth
421 /* 238, 0x0ee */ SDL_SCANCODE_UNKNOWN, // XF86WLAN
422 /* 239, 0x0ef */ SDL_SCANCODE_UNKNOWN, // XF86UWB
423 /* 240, 0x0f0 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
424 /* 241, 0x0f1 */ SDL_SCANCODE_UNKNOWN, // XF86Next_VMode
425 /* 242, 0x0f2 */ SDL_SCANCODE_UNKNOWN, // XF86Prev_VMode
426 /* 243, 0x0f3 */ SDL_SCANCODE_UNKNOWN, // XF86MonBrightnessCycle
427 /* 244, 0x0f4 */ SDL_SCANCODE_UNKNOWN, // XF86BrightnessAuto
428 /* 245, 0x0f5 */ SDL_SCANCODE_UNKNOWN, // XF86DisplayOff
429 /* 246, 0x0f6 */ SDL_SCANCODE_UNKNOWN, // XF86WWAN
430 /* 247, 0x0f7 */ SDL_SCANCODE_UNKNOWN, // XF86RFKill
431};
432
433// Xvnc / Xtightvnc scancodes from xmodmap -pk
434static const SDL_Scancode xvnc_scancode_table[] = {
435 /* 0 */ SDL_SCANCODE_LCTRL,
436 /* 1 */ SDL_SCANCODE_RCTRL,
437 /* 2 */ SDL_SCANCODE_LSHIFT,
438 /* 3 */ SDL_SCANCODE_RSHIFT,
439 /* 4 */ SDL_SCANCODE_UNKNOWN, // Meta_L
440 /* 5 */ SDL_SCANCODE_UNKNOWN, // Meta_R
441 /* 6 */ SDL_SCANCODE_LALT,
442 /* 7 */ SDL_SCANCODE_RALT,
443 /* 8 */ SDL_SCANCODE_SPACE,
444 /* 9 */ SDL_SCANCODE_0,
445 /* 10 */ SDL_SCANCODE_1,
446 /* 11 */ SDL_SCANCODE_2,
447 /* 12 */ SDL_SCANCODE_3,
448 /* 13 */ SDL_SCANCODE_4,
449 /* 14 */ SDL_SCANCODE_5,
450 /* 15 */ SDL_SCANCODE_6,
451 /* 16 */ SDL_SCANCODE_7,
452 /* 17 */ SDL_SCANCODE_8,
453 /* 18 */ SDL_SCANCODE_9,
454 /* 19 */ SDL_SCANCODE_MINUS,
455 /* 20 */ SDL_SCANCODE_EQUALS,
456 /* 21 */ SDL_SCANCODE_LEFTBRACKET,
457 /* 22 */ SDL_SCANCODE_RIGHTBRACKET,
458 /* 23 */ SDL_SCANCODE_SEMICOLON,
459 /* 24 */ SDL_SCANCODE_APOSTROPHE,
460 /* 25 */ SDL_SCANCODE_GRAVE,
461 /* 26 */ SDL_SCANCODE_COMMA,
462 /* 27 */ SDL_SCANCODE_PERIOD,
463 /* 28 */ SDL_SCANCODE_SLASH,
464 /* 29 */ SDL_SCANCODE_BACKSLASH,
465 /* 30 */ SDL_SCANCODE_A,
466 /* 31 */ SDL_SCANCODE_B,
467 /* 32 */ SDL_SCANCODE_C,
468 /* 33 */ SDL_SCANCODE_D,
469 /* 34 */ SDL_SCANCODE_E,
470 /* 35 */ SDL_SCANCODE_F,
471 /* 36 */ SDL_SCANCODE_G,
472 /* 37 */ SDL_SCANCODE_H,
473 /* 38 */ SDL_SCANCODE_I,
474 /* 39 */ SDL_SCANCODE_J,
475 /* 40 */ SDL_SCANCODE_K,
476 /* 41 */ SDL_SCANCODE_L,
477 /* 42 */ SDL_SCANCODE_M,
478 /* 43 */ SDL_SCANCODE_N,
479 /* 44 */ SDL_SCANCODE_O,
480 /* 45 */ SDL_SCANCODE_P,
481 /* 46 */ SDL_SCANCODE_Q,
482 /* 47 */ SDL_SCANCODE_R,
483 /* 48 */ SDL_SCANCODE_S,
484 /* 49 */ SDL_SCANCODE_T,
485 /* 50 */ SDL_SCANCODE_U,
486 /* 51 */ SDL_SCANCODE_V,
487 /* 52 */ SDL_SCANCODE_W,
488 /* 53 */ SDL_SCANCODE_X,
489 /* 54 */ SDL_SCANCODE_Y,
490 /* 55 */ SDL_SCANCODE_Z,
491 /* 56 */ SDL_SCANCODE_BACKSPACE,
492 /* 57 */ SDL_SCANCODE_RETURN,
493 /* 58 */ SDL_SCANCODE_TAB,
494 /* 59 */ SDL_SCANCODE_ESCAPE,
495 /* 60 */ SDL_SCANCODE_DELETE,
496 /* 61 */ SDL_SCANCODE_HOME,
497 /* 62 */ SDL_SCANCODE_END,
498 /* 63 */ SDL_SCANCODE_PAGEUP,
499 /* 64 */ SDL_SCANCODE_PAGEDOWN,
500 /* 65 */ SDL_SCANCODE_UP,
501 /* 66 */ SDL_SCANCODE_DOWN,
502 /* 67 */ SDL_SCANCODE_LEFT,
503 /* 68 */ SDL_SCANCODE_RIGHT,
504 /* 69 */ SDL_SCANCODE_F1,
505 /* 70 */ SDL_SCANCODE_F2,
506 /* 71 */ SDL_SCANCODE_F3,
507 /* 72 */ SDL_SCANCODE_F4,
508 /* 73 */ SDL_SCANCODE_F5,
509 /* 74 */ SDL_SCANCODE_F6,
510 /* 75 */ SDL_SCANCODE_F7,
511 /* 76 */ SDL_SCANCODE_F8,
512 /* 77 */ SDL_SCANCODE_F9,
513 /* 78 */ SDL_SCANCODE_F10,
514 /* 79 */ SDL_SCANCODE_F11,
515 /* 80 */ SDL_SCANCODE_F12,
516};
517
518#endif // scancodes_xfree86_h_
519
520/* *INDENT-ON* */ // clang-format on