diff options
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/checkkeys.c')
-rw-r--r-- | src/contrib/SDL-3.2.20/test/checkkeys.c | 531 |
1 files changed, 531 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/test/checkkeys.c b/src/contrib/SDL-3.2.20/test/checkkeys.c new file mode 100644 index 0000000..ab7df8e --- /dev/null +++ b/src/contrib/SDL-3.2.20/test/checkkeys.c | |||
@@ -0,0 +1,531 @@ | |||
1 | /* | ||
2 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
3 | |||
4 | This software is provided 'as-is', without any express or implied | ||
5 | warranty. In no event will the authors be held liable for any damages | ||
6 | arising from the use of this software. | ||
7 | |||
8 | Permission is granted to anyone to use this software for any purpose, | ||
9 | including commercial applications, and to alter it and redistribute it | ||
10 | freely. | ||
11 | */ | ||
12 | |||
13 | /* Simple program: Loop, watching keystrokes | ||
14 | Note that you need to call SDL_PollEvent() or SDL_WaitEvent() to | ||
15 | pump the event loop and catch keystrokes. | ||
16 | */ | ||
17 | |||
18 | #include <SDL3/SDL.h> | ||
19 | #include <SDL3/SDL_main.h> | ||
20 | #include <SDL3/SDL_test.h> | ||
21 | |||
22 | #ifdef SDL_PLATFORM_EMSCRIPTEN | ||
23 | #include <emscripten/emscripten.h> | ||
24 | #endif | ||
25 | |||
26 | #define TEXT_WINDOW_OFFSET_X 2.0f | ||
27 | #define TEXT_WINDOW_OFFSET_Y (2.0f + FONT_LINE_HEIGHT) | ||
28 | |||
29 | #define CURSOR_BLINK_INTERVAL_MS 500 | ||
30 | |||
31 | typedef struct | ||
32 | { | ||
33 | SDLTest_TextWindow *textwindow; | ||
34 | char *edit_text; | ||
35 | int edit_cursor; | ||
36 | int edit_length; | ||
37 | } TextWindowState; | ||
38 | |||
39 | static SDLTest_CommonState *state; | ||
40 | static TextWindowState *windowstates; | ||
41 | static bool escape_pressed; | ||
42 | static bool cursor_visible; | ||
43 | static Uint64 last_cursor_change; | ||
44 | static int done; | ||
45 | |||
46 | static TextWindowState *GetTextWindowStateForWindowID(SDL_WindowID id) | ||
47 | { | ||
48 | int i; | ||
49 | |||
50 | for (i = 0; i < state->num_windows; ++i) { | ||
51 | if (id == SDL_GetWindowID(state->windows[i])) { | ||
52 | return &windowstates[i]; | ||
53 | } | ||
54 | } | ||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | static SDLTest_TextWindow *GetTextWindowForWindowID(SDL_WindowID id) | ||
59 | { | ||
60 | TextWindowState *windowstate = GetTextWindowStateForWindowID(id); | ||
61 | if (windowstate) { | ||
62 | return windowstate->textwindow; | ||
63 | } | ||
64 | return NULL; | ||
65 | } | ||
66 | |||
67 | static void UpdateTextWindowInputRect(SDL_WindowID id) | ||
68 | { | ||
69 | int i; | ||
70 | |||
71 | for (i = 0; i < state->num_windows; ++i) { | ||
72 | if (id == SDL_GetWindowID(state->windows[i])) { | ||
73 | SDLTest_TextWindow *textwindow = windowstates[i].textwindow; | ||
74 | int w, h; | ||
75 | SDL_Rect rect; | ||
76 | int cursor = 0; | ||
77 | int current = textwindow->current; | ||
78 | const char *current_line = textwindow->lines[current]; | ||
79 | |||
80 | SDL_GetWindowSize(state->windows[i], &w, &h); | ||
81 | |||
82 | if (current_line) { | ||
83 | cursor = (int)SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE; | ||
84 | } | ||
85 | |||
86 | rect.x = (int)TEXT_WINDOW_OFFSET_X; | ||
87 | rect.y = (int)TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT; | ||
88 | rect.w = (int)(w - (2 * TEXT_WINDOW_OFFSET_X)); | ||
89 | rect.h = FONT_CHARACTER_SIZE; | ||
90 | SDL_SetTextInputArea(state->windows[i], &rect, cursor); | ||
91 | return; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static void print_string(char **text, size_t *maxlen, const char *fmt, ...) | ||
97 | { | ||
98 | int len; | ||
99 | va_list ap; | ||
100 | |||
101 | va_start(ap, fmt); | ||
102 | len = SDL_vsnprintf(*text, *maxlen, fmt, ap); | ||
103 | if (len > 0) { | ||
104 | *text += len; | ||
105 | if (((size_t)len) < *maxlen) { | ||
106 | *maxlen -= (size_t)len; | ||
107 | } else { | ||
108 | *maxlen = 0; | ||
109 | } | ||
110 | } | ||
111 | va_end(ap); | ||
112 | } | ||
113 | |||
114 | static void print_modifiers(char **text, size_t *maxlen, SDL_Keymod mod) | ||
115 | { | ||
116 | print_string(text, maxlen, " modifiers:"); | ||
117 | if (mod == SDL_KMOD_NONE) { | ||
118 | print_string(text, maxlen, " (none)"); | ||
119 | return; | ||
120 | } | ||
121 | if ((mod & SDL_KMOD_SHIFT) == SDL_KMOD_SHIFT) { | ||
122 | print_string(text, maxlen, " SHIFT"); | ||
123 | } else { | ||
124 | if (mod & SDL_KMOD_LSHIFT) { | ||
125 | print_string(text, maxlen, " LSHIFT"); | ||
126 | } | ||
127 | if (mod & SDL_KMOD_RSHIFT) { | ||
128 | print_string(text, maxlen, " RSHIFT"); | ||
129 | } | ||
130 | } | ||
131 | if ((mod & SDL_KMOD_CTRL) == SDL_KMOD_CTRL) { | ||
132 | print_string(text, maxlen, " CTRL"); | ||
133 | } else { | ||
134 | if (mod & SDL_KMOD_LCTRL) { | ||
135 | print_string(text, maxlen, " LCTRL"); | ||
136 | } | ||
137 | if (mod & SDL_KMOD_RCTRL) { | ||
138 | print_string(text, maxlen, " RCTRL"); | ||
139 | } | ||
140 | } | ||
141 | if ((mod & SDL_KMOD_ALT) == SDL_KMOD_ALT) { | ||
142 | print_string(text, maxlen, " ALT"); | ||
143 | } else { | ||
144 | if (mod & SDL_KMOD_LALT) { | ||
145 | print_string(text, maxlen, " LALT"); | ||
146 | } | ||
147 | if (mod & SDL_KMOD_RALT) { | ||
148 | print_string(text, maxlen, " RALT"); | ||
149 | } | ||
150 | } | ||
151 | if ((mod & SDL_KMOD_GUI) == SDL_KMOD_GUI) { | ||
152 | print_string(text, maxlen, " GUI"); | ||
153 | } else { | ||
154 | if (mod & SDL_KMOD_LGUI) { | ||
155 | print_string(text, maxlen, " LGUI"); | ||
156 | } | ||
157 | if (mod & SDL_KMOD_RGUI) { | ||
158 | print_string(text, maxlen, " RGUI"); | ||
159 | } | ||
160 | } | ||
161 | if (mod & SDL_KMOD_NUM) { | ||
162 | print_string(text, maxlen, " NUM"); | ||
163 | } | ||
164 | if (mod & SDL_KMOD_CAPS) { | ||
165 | print_string(text, maxlen, " CAPS"); | ||
166 | } | ||
167 | if (mod & SDL_KMOD_MODE) { | ||
168 | print_string(text, maxlen, " MODE"); | ||
169 | } | ||
170 | if (mod & SDL_KMOD_LEVEL5) { | ||
171 | print_string(text, maxlen, " LEVEL5"); | ||
172 | } | ||
173 | if (mod & SDL_KMOD_SCROLL) { | ||
174 | print_string(text, maxlen, " SCROLL"); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | static void PrintModifierState(void) | ||
179 | { | ||
180 | char message[512]; | ||
181 | char *spot; | ||
182 | size_t left; | ||
183 | |||
184 | spot = message; | ||
185 | left = sizeof(message); | ||
186 | |||
187 | print_modifiers(&spot, &left, SDL_GetModState()); | ||
188 | SDL_Log("Initial state:%s", message); | ||
189 | } | ||
190 | |||
191 | static void PrintKey(SDL_KeyboardEvent *event) | ||
192 | { | ||
193 | char message[512]; | ||
194 | char *spot; | ||
195 | size_t left; | ||
196 | |||
197 | spot = message; | ||
198 | left = sizeof(message); | ||
199 | |||
200 | /* Print the keycode, name and state */ | ||
201 | if (event->key) { | ||
202 | print_string(&spot, &left, | ||
203 | "Key %s: raw 0x%.2x, scancode %d = %s, keycode 0x%08X = %s ", | ||
204 | event->down ? "pressed " : "released", | ||
205 | event->raw, | ||
206 | event->scancode, | ||
207 | event->scancode == SDL_SCANCODE_UNKNOWN ? "UNKNOWN" : SDL_GetScancodeName(event->scancode), | ||
208 | event->key, SDL_GetKeyName(event->key)); | ||
209 | } else { | ||
210 | print_string(&spot, &left, | ||
211 | "Unknown Key (raw 0x%.2x, scancode %d = %s) %s ", | ||
212 | event->raw, | ||
213 | event->scancode, | ||
214 | event->scancode == SDL_SCANCODE_UNKNOWN ? "UNKNOWN" : SDL_GetScancodeName(event->scancode), | ||
215 | event->down ? "pressed " : "released"); | ||
216 | } | ||
217 | print_modifiers(&spot, &left, event->mod); | ||
218 | if (event->repeat) { | ||
219 | print_string(&spot, &left, " (repeat)"); | ||
220 | } | ||
221 | SDL_Log("%s", message); | ||
222 | } | ||
223 | |||
224 | static void PrintText(const char *eventtype, const char *text) | ||
225 | { | ||
226 | const char *spot; | ||
227 | char expanded[1024]; | ||
228 | |||
229 | expanded[0] = '\0'; | ||
230 | for (spot = text; *spot; ++spot) { | ||
231 | size_t length = SDL_strlen(expanded); | ||
232 | (void)SDL_snprintf(expanded + length, sizeof(expanded) - length, "\\x%.2x", (unsigned char)*spot); | ||
233 | } | ||
234 | SDL_Log("%s Text (%s): \"%s%s\"", eventtype, expanded, *text == '"' ? "\\" : "", text); | ||
235 | } | ||
236 | |||
237 | static void CountKeysDown(void) | ||
238 | { | ||
239 | int i, count = 0, max_keys = 0; | ||
240 | const bool *keystate = SDL_GetKeyboardState(&max_keys); | ||
241 | |||
242 | for (i = 0; i < max_keys; ++i) { | ||
243 | if (keystate[i]) { | ||
244 | ++count; | ||
245 | } | ||
246 | } | ||
247 | SDL_Log("Keys down: %d", count); | ||
248 | } | ||
249 | |||
250 | static void DrawCursor(int i) | ||
251 | { | ||
252 | SDL_FRect rect; | ||
253 | TextWindowState *windowstate = &windowstates[i]; | ||
254 | SDLTest_TextWindow *textwindow = windowstate->textwindow; | ||
255 | int current = textwindow->current; | ||
256 | const char *current_line = textwindow->lines[current]; | ||
257 | |||
258 | rect.x = TEXT_WINDOW_OFFSET_X; | ||
259 | if (current_line) { | ||
260 | rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE; | ||
261 | } | ||
262 | if (windowstate->edit_cursor > 0) { | ||
263 | rect.x += (float)windowstate->edit_cursor * FONT_CHARACTER_SIZE; | ||
264 | } | ||
265 | rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT; | ||
266 | rect.w = FONT_CHARACTER_SIZE * 0.75f; | ||
267 | rect.h = (float)FONT_CHARACTER_SIZE; | ||
268 | |||
269 | SDL_SetRenderDrawColor(state->renderers[i], 0xAA, 0xAA, 0xAA, 255); | ||
270 | SDL_RenderFillRect(state->renderers[i], &rect); | ||
271 | } | ||
272 | |||
273 | static void DrawEditText(int i) | ||
274 | { | ||
275 | SDL_FRect rect; | ||
276 | TextWindowState *windowstate = &windowstates[i]; | ||
277 | SDLTest_TextWindow *textwindow = windowstate->textwindow; | ||
278 | int current = textwindow->current; | ||
279 | const char *current_line = textwindow->lines[current]; | ||
280 | |||
281 | if (windowstate->edit_text == NULL) { | ||
282 | return; | ||
283 | } | ||
284 | |||
285 | /* Draw the highlight under the selected text */ | ||
286 | if (windowstate->edit_length > 0) { | ||
287 | rect.x = TEXT_WINDOW_OFFSET_X; | ||
288 | if (current_line) { | ||
289 | rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE; | ||
290 | } | ||
291 | if (windowstate->edit_cursor > 0) { | ||
292 | rect.x += (float)windowstate->edit_cursor * FONT_CHARACTER_SIZE; | ||
293 | } | ||
294 | rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT; | ||
295 | rect.w = (float)windowstate->edit_length * FONT_CHARACTER_SIZE; | ||
296 | rect.h = (float)FONT_CHARACTER_SIZE; | ||
297 | |||
298 | SDL_SetRenderDrawColor(state->renderers[i], 0xAA, 0xAA, 0xAA, 255); | ||
299 | SDL_RenderFillRect(state->renderers[i], &rect); | ||
300 | } | ||
301 | |||
302 | /* Draw the edit text */ | ||
303 | rect.x = TEXT_WINDOW_OFFSET_X; | ||
304 | if (current_line) { | ||
305 | rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE; | ||
306 | } | ||
307 | rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT; | ||
308 | SDL_SetRenderDrawColor(state->renderers[i], 255, 255, 0, 255); | ||
309 | SDLTest_DrawString(state->renderers[i], rect.x, rect.y, windowstate->edit_text); | ||
310 | } | ||
311 | |||
312 | static void loop(void) | ||
313 | { | ||
314 | SDL_Event event; | ||
315 | Uint64 now; | ||
316 | int i; | ||
317 | char line[1024]; | ||
318 | |||
319 | while (SDL_PollEvent(&event)) { | ||
320 | switch (event.type) { | ||
321 | case SDL_EVENT_KEY_DOWN: | ||
322 | case SDL_EVENT_KEY_UP: | ||
323 | PrintKey(&event.key); | ||
324 | if (event.type == SDL_EVENT_KEY_DOWN) { | ||
325 | switch (event.key.key) { | ||
326 | case SDLK_BACKSPACE: | ||
327 | SDLTest_TextWindowAddText(GetTextWindowForWindowID(event.key.windowID), "\b"); | ||
328 | UpdateTextWindowInputRect(event.key.windowID); | ||
329 | break; | ||
330 | case SDLK_RETURN: | ||
331 | SDLTest_TextWindowAddText(GetTextWindowForWindowID(event.key.windowID), "\n"); | ||
332 | UpdateTextWindowInputRect(event.key.windowID); | ||
333 | break; | ||
334 | default: | ||
335 | break; | ||
336 | } | ||
337 | if (event.key.key == SDLK_ESCAPE) { | ||
338 | /* Pressing escape twice will stop the application */ | ||
339 | if (escape_pressed) { | ||
340 | done = 1; | ||
341 | } else { | ||
342 | escape_pressed = true; | ||
343 | } | ||
344 | } else { | ||
345 | escape_pressed = true; | ||
346 | } | ||
347 | } | ||
348 | CountKeysDown(); | ||
349 | break; | ||
350 | case SDL_EVENT_TEXT_EDITING: | ||
351 | { | ||
352 | TextWindowState *windowstate = GetTextWindowStateForWindowID(event.edit.windowID); | ||
353 | if (windowstate->edit_text) { | ||
354 | SDL_free(windowstate->edit_text); | ||
355 | windowstate->edit_text = NULL; | ||
356 | } | ||
357 | if (event.edit.text && *event.edit.text) { | ||
358 | windowstate->edit_text = SDL_strdup(event.edit.text); | ||
359 | } | ||
360 | windowstate->edit_cursor = event.edit.start; | ||
361 | windowstate->edit_length = event.edit.length; | ||
362 | |||
363 | SDL_snprintf(line, sizeof(line), "EDIT %" SDL_PRIs32 ":%" SDL_PRIs32, event.edit.start, event.edit.length); | ||
364 | PrintText(line, event.edit.text); | ||
365 | break; | ||
366 | } | ||
367 | case SDL_EVENT_TEXT_INPUT: | ||
368 | PrintText("INPUT", event.text.text); | ||
369 | SDLTest_TextWindowAddText(GetTextWindowForWindowID(event.text.windowID), "%s", event.text.text); | ||
370 | UpdateTextWindowInputRect(event.text.windowID); | ||
371 | break; | ||
372 | case SDL_EVENT_FINGER_DOWN: | ||
373 | { | ||
374 | SDL_Window *window = SDL_GetWindowFromEvent(&event); | ||
375 | if (SDL_TextInputActive(window)) { | ||
376 | SDL_Log("Stopping text input for window %" SDL_PRIu32, event.tfinger.windowID); | ||
377 | SDL_StopTextInput(window); | ||
378 | } else { | ||
379 | SDL_Log("Starting text input for window %" SDL_PRIu32, event.tfinger.windowID); | ||
380 | SDL_StartTextInput(window); | ||
381 | } | ||
382 | break; | ||
383 | } | ||
384 | case SDL_EVENT_MOUSE_BUTTON_DOWN: | ||
385 | if (event.button.button == SDL_BUTTON_RIGHT) { | ||
386 | SDL_Window *window = SDL_GetWindowFromEvent(&event); | ||
387 | if (SDL_TextInputActive(window)) { | ||
388 | SDL_Log("Stopping text input for window %" SDL_PRIu32, event.button.windowID); | ||
389 | SDL_StopTextInput(window); | ||
390 | } else { | ||
391 | SDL_Log("Starting text input for window %" SDL_PRIu32, event.button.windowID); | ||
392 | SDL_StartTextInput(window); | ||
393 | } | ||
394 | } | ||
395 | break; | ||
396 | case SDL_EVENT_KEYMAP_CHANGED: | ||
397 | SDL_Log("Keymap changed!"); | ||
398 | break; | ||
399 | case SDL_EVENT_QUIT: | ||
400 | done = 1; | ||
401 | break; | ||
402 | default: | ||
403 | break; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | now = SDL_GetTicks(); | ||
408 | for (i = 0; i < state->num_windows; i++) { | ||
409 | char caption[1024]; | ||
410 | |||
411 | /* Clear the window */ | ||
412 | SDL_SetRenderDrawColor(state->renderers[i], 0, 0, 0, 255); | ||
413 | SDL_RenderClear(state->renderers[i]); | ||
414 | |||
415 | /* Draw the text */ | ||
416 | SDL_SetRenderDrawColor(state->renderers[i], 255, 255, 255, 255); | ||
417 | SDL_snprintf(caption, sizeof(caption), "Text input %s (click right mouse button to toggle)\n", SDL_TextInputActive(state->windows[i]) ? "enabled" : "disabled"); | ||
418 | SDLTest_DrawString(state->renderers[i], TEXT_WINDOW_OFFSET_X, TEXT_WINDOW_OFFSET_X, caption); | ||
419 | SDLTest_TextWindowDisplay(windowstates[i].textwindow, state->renderers[i]); | ||
420 | |||
421 | /* Draw the cursor */ | ||
422 | if ((now - last_cursor_change) >= CURSOR_BLINK_INTERVAL_MS) { | ||
423 | cursor_visible = !cursor_visible; | ||
424 | last_cursor_change = now; | ||
425 | } | ||
426 | if (cursor_visible) { | ||
427 | DrawCursor(i); | ||
428 | } | ||
429 | |||
430 | /* Draw the composition text */ | ||
431 | DrawEditText(i); | ||
432 | |||
433 | SDL_RenderPresent(state->renderers[i]); | ||
434 | } | ||
435 | |||
436 | /* Slow down framerate */ | ||
437 | SDL_Delay(100); | ||
438 | |||
439 | #ifdef SDL_PLATFORM_EMSCRIPTEN | ||
440 | if (done) { | ||
441 | emscripten_cancel_main_loop(); | ||
442 | } | ||
443 | #endif | ||
444 | } | ||
445 | |||
446 | int main(int argc, char *argv[]) | ||
447 | { | ||
448 | int i; | ||
449 | |||
450 | SDL_SetHint(SDL_HINT_WINDOWS_RAW_KEYBOARD, "1"); | ||
451 | |||
452 | /* Initialize test framework */ | ||
453 | state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); | ||
454 | if (!state) { | ||
455 | return 1; | ||
456 | } | ||
457 | state->window_title = "CheckKeys Test"; | ||
458 | |||
459 | /* Parse commandline */ | ||
460 | if (!SDLTest_CommonDefaultArgs(state, argc, argv)) { | ||
461 | return 1; | ||
462 | } | ||
463 | |||
464 | /* Disable mouse emulation */ | ||
465 | SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); | ||
466 | |||
467 | /* Initialize SDL */ | ||
468 | if (!SDLTest_CommonInit(state)) { | ||
469 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); | ||
470 | return 1; | ||
471 | } | ||
472 | |||
473 | windowstates = (TextWindowState *)SDL_calloc(state->num_windows, sizeof(*windowstates)); | ||
474 | if (!windowstates) { | ||
475 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't allocate text windows: %s", SDL_GetError()); | ||
476 | goto done; | ||
477 | } | ||
478 | |||
479 | for (i = 0; i < state->num_windows; ++i) { | ||
480 | int w, h; | ||
481 | SDL_FRect rect; | ||
482 | |||
483 | SDL_GetWindowSize(state->windows[i], &w, &h); | ||
484 | rect.x = TEXT_WINDOW_OFFSET_X; | ||
485 | rect.y = TEXT_WINDOW_OFFSET_Y; | ||
486 | rect.w = w - (2 * TEXT_WINDOW_OFFSET_X); | ||
487 | rect.h = h - TEXT_WINDOW_OFFSET_Y; | ||
488 | windowstates[i].textwindow = SDLTest_TextWindowCreate(rect.x, rect.y, rect.w, rect.h); | ||
489 | } | ||
490 | |||
491 | #ifdef SDL_PLATFORM_IOS | ||
492 | { | ||
493 | /* Creating the context creates the view, which we need to show keyboard */ | ||
494 | for (i = 0; i < state->num_windows; i++) { | ||
495 | SDL_GL_CreateContext(state->windows[i]); | ||
496 | } | ||
497 | } | ||
498 | #endif | ||
499 | |||
500 | for (i = 0; i < state->num_windows; ++i) { | ||
501 | UpdateTextWindowInputRect(SDL_GetWindowID(state->windows[i])); | ||
502 | |||
503 | SDL_StartTextInput(state->windows[i]); | ||
504 | } | ||
505 | |||
506 | /* Print initial state */ | ||
507 | SDL_PumpEvents(); | ||
508 | PrintModifierState(); | ||
509 | |||
510 | /* Watch keystrokes */ | ||
511 | done = 0; | ||
512 | |||
513 | #ifdef SDL_PLATFORM_EMSCRIPTEN | ||
514 | emscripten_set_main_loop(loop, 0, 1); | ||
515 | #else | ||
516 | while (!done) { | ||
517 | loop(); | ||
518 | } | ||
519 | #endif | ||
520 | |||
521 | done: | ||
522 | if (windowstates) { | ||
523 | for (i = 0; i < state->num_windows; ++i) { | ||
524 | SDLTest_TextWindowDestroy(windowstates[i].textwindow); | ||
525 | } | ||
526 | SDL_free(windowstates); | ||
527 | } | ||
528 | SDLTest_CleanupTextDrawing(); | ||
529 | SDLTest_CommonQuit(state); | ||
530 | return 0; | ||
531 | } | ||