1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2021 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/* Ported from original test/common.c file. */
23
24#include "SDL_config.h"
25#include "SDL_test.h"
26
27#include <stdio.h>
28
29static const char *video_usage[] = {
30 "[--video driver]", "[--renderer driver]", "[--gldebug]",
31 "[--info all|video|modes|render|event]",
32 "[--log all|error|system|audio|video|render|input]", "[--display N]",
33 "[--metal-window | --opengl-window | --vulkan-window]",
34 "[--fullscreen | --fullscreen-desktop | --windows N]", "[--title title]",
35 "[--icon icon.bmp]", "[--center | --position X,Y]", "[--geometry WxH]",
36 "[--min-geometry WxH]", "[--max-geometry WxH]", "[--logical WxH]",
37 "[--scale N]", "[--depth N]", "[--refresh R]", "[--vsync]", "[--noframe]",
38 "[--resize]", "[--minimize]", "[--maximize]", "[--grab]", "[--keyboard-grab]",
39 "[--allow-highdpi]", "[--usable-bounds]"
40};
41
42static const char *audio_usage[] = {
43 "[--rate N]", "[--format U8|S8|U16|U16LE|U16BE|S16|S16LE|S16BE]",
44 "[--channels N]", "[--samples N]"
45};
46
47static void SDL_snprintfcat(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... )
48{
49 size_t length = SDL_strlen(text);
50 va_list ap;
51
52 va_start(ap, fmt);
53 text += length;
54 maxlen -= length;
55 SDL_vsnprintf(text, maxlen, fmt, ap);
56 va_end(ap);
57}
58
59SDLTest_CommonState *
60SDLTest_CommonCreateState(char **argv, Uint32 flags)
61{
62 int i;
63 SDLTest_CommonState *state;
64
65 /* Do this first so we catch all allocations */
66 for (i = 1; argv[i]; ++i) {
67 if (SDL_strcasecmp(argv[i], "--trackmem") == 0) {
68 SDLTest_TrackAllocations();
69 break;
70 }
71 }
72
73 state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state));
74 if (!state) {
75 SDL_OutOfMemory();
76 return NULL;
77 }
78
79 /* Initialize some defaults */
80 state->argv = argv;
81 state->flags = flags;
82 state->window_title = argv[0];
83 state->window_flags = 0;
84 state->window_x = SDL_WINDOWPOS_UNDEFINED;
85 state->window_y = SDL_WINDOWPOS_UNDEFINED;
86 state->window_w = DEFAULT_WINDOW_WIDTH;
87 state->window_h = DEFAULT_WINDOW_HEIGHT;
88 state->num_windows = 1;
89 state->audiospec.freq = 22050;
90 state->audiospec.format = AUDIO_S16;
91 state->audiospec.channels = 2;
92 state->audiospec.samples = 2048;
93
94 /* Set some very sane GL defaults */
95 state->gl_red_size = 3;
96 state->gl_green_size = 3;
97 state->gl_blue_size = 2;
98 state->gl_alpha_size = 0;
99 state->gl_buffer_size = 0;
100 state->gl_depth_size = 16;
101 state->gl_stencil_size = 0;
102 state->gl_double_buffer = 1;
103 state->gl_accum_red_size = 0;
104 state->gl_accum_green_size = 0;
105 state->gl_accum_blue_size = 0;
106 state->gl_accum_alpha_size = 0;
107 state->gl_stereo = 0;
108 state->gl_multisamplebuffers = 0;
109 state->gl_multisamplesamples = 0;
110 state->gl_retained_backing = 1;
111 state->gl_accelerated = -1;
112 state->gl_debug = 0;
113
114 return state;
115}
116
117int
118SDLTest_CommonArg(SDLTest_CommonState * state, int index)
119{
120 char **argv = state->argv;
121
122 if (SDL_strcasecmp(argv[index], "--video") == 0) {
123 ++index;
124 if (!argv[index]) {
125 return -1;
126 }
127 state->videodriver = argv[index];
128 return 2;
129 }
130 if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
131 ++index;
132 if (!argv[index]) {
133 return -1;
134 }
135 state->renderdriver = argv[index];
136 return 2;
137 }
138 if (SDL_strcasecmp(argv[index], "--gldebug") == 0) {
139 state->gl_debug = 1;
140 return 1;
141 }
142 if (SDL_strcasecmp(argv[index], "--info") == 0) {
143 ++index;
144 if (!argv[index]) {
145 return -1;
146 }
147 if (SDL_strcasecmp(argv[index], "all") == 0) {
148 state->verbose |=
149 (VERBOSE_VIDEO | VERBOSE_MODES | VERBOSE_RENDER |
150 VERBOSE_EVENT);
151 return 2;
152 }
153 if (SDL_strcasecmp(argv[index], "video") == 0) {
154 state->verbose |= VERBOSE_VIDEO;
155 return 2;
156 }
157 if (SDL_strcasecmp(argv[index], "modes") == 0) {
158 state->verbose |= VERBOSE_MODES;
159 return 2;
160 }
161 if (SDL_strcasecmp(argv[index], "render") == 0) {
162 state->verbose |= VERBOSE_RENDER;
163 return 2;
164 }
165 if (SDL_strcasecmp(argv[index], "event") == 0) {
166 state->verbose |= VERBOSE_EVENT;
167 return 2;
168 }
169 return -1;
170 }
171 if (SDL_strcasecmp(argv[index], "--log") == 0) {
172 ++index;
173 if (!argv[index]) {
174 return -1;
175 }
176 if (SDL_strcasecmp(argv[index], "all") == 0) {
177 SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
178 return 2;
179 }
180 if (SDL_strcasecmp(argv[index], "error") == 0) {
181 SDL_LogSetPriority(SDL_LOG_CATEGORY_ERROR, SDL_LOG_PRIORITY_VERBOSE);
182 return 2;
183 }
184 if (SDL_strcasecmp(argv[index], "system") == 0) {
185 SDL_LogSetPriority(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE);
186 return 2;
187 }
188 if (SDL_strcasecmp(argv[index], "audio") == 0) {
189 SDL_LogSetPriority(SDL_LOG_CATEGORY_AUDIO, SDL_LOG_PRIORITY_VERBOSE);
190 return 2;
191 }
192 if (SDL_strcasecmp(argv[index], "video") == 0) {
193 SDL_LogSetPriority(SDL_LOG_CATEGORY_VIDEO, SDL_LOG_PRIORITY_VERBOSE);
194 return 2;
195 }
196 if (SDL_strcasecmp(argv[index], "render") == 0) {
197 SDL_LogSetPriority(SDL_LOG_CATEGORY_RENDER, SDL_LOG_PRIORITY_VERBOSE);
198 return 2;
199 }
200 if (SDL_strcasecmp(argv[index], "input") == 0) {
201 SDL_LogSetPriority(SDL_LOG_CATEGORY_INPUT, SDL_LOG_PRIORITY_VERBOSE);
202 return 2;
203 }
204 return -1;
205 }
206 if (SDL_strcasecmp(argv[index], "--display") == 0) {
207 ++index;
208 if (!argv[index]) {
209 return -1;
210 }
211 state->display = SDL_atoi(argv[index]);
212 if (SDL_WINDOWPOS_ISUNDEFINED(state->window_x)) {
213 state->window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
214 state->window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
215 }
216 if (SDL_WINDOWPOS_ISCENTERED(state->window_x)) {
217 state->window_x = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
218 state->window_y = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
219 }
220 return 2;
221 }
222 if (SDL_strcasecmp(argv[index], "--metal-window") == 0) {
223 state->window_flags |= SDL_WINDOW_METAL;
224 return 1;
225 }
226 if (SDL_strcasecmp(argv[index], "--opengl-window") == 0) {
227 state->window_flags |= SDL_WINDOW_OPENGL;
228 return 1;
229 }
230 if (SDL_strcasecmp(argv[index], "--vulkan-window") == 0) {
231 state->window_flags |= SDL_WINDOW_VULKAN;
232 return 1;
233 }
234 if (SDL_strcasecmp(argv[index], "--fullscreen") == 0) {
235 state->window_flags |= SDL_WINDOW_FULLSCREEN;
236 state->num_windows = 1;
237 return 1;
238 }
239 if (SDL_strcasecmp(argv[index], "--fullscreen-desktop") == 0) {
240 state->window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
241 state->num_windows = 1;
242 return 1;
243 }
244 if (SDL_strcasecmp(argv[index], "--allow-highdpi") == 0) {
245 state->window_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
246 return 1;
247 }
248 if (SDL_strcasecmp(argv[index], "--windows") == 0) {
249 ++index;
250 if (!argv[index] || !SDL_isdigit(*argv[index])) {
251 return -1;
252 }
253 if (!(state->window_flags & SDL_WINDOW_FULLSCREEN)) {
254 state->num_windows = SDL_atoi(argv[index]);
255 }
256 return 2;
257 }
258 if (SDL_strcasecmp(argv[index], "--title") == 0) {
259 ++index;
260 if (!argv[index]) {
261 return -1;
262 }
263 state->window_title = argv[index];
264 return 2;
265 }
266 if (SDL_strcasecmp(argv[index], "--icon") == 0) {
267 ++index;
268 if (!argv[index]) {
269 return -1;
270 }
271 state->window_icon = argv[index];
272 return 2;
273 }
274 if (SDL_strcasecmp(argv[index], "--center") == 0) {
275 state->window_x = SDL_WINDOWPOS_CENTERED;
276 state->window_y = SDL_WINDOWPOS_CENTERED;
277 return 1;
278 }
279 if (SDL_strcasecmp(argv[index], "--position") == 0) {
280 char *x, *y;
281 ++index;
282 if (!argv[index]) {
283 return -1;
284 }
285 x = argv[index];
286 y = argv[index];
287 while (*y && *y != ',') {
288 ++y;
289 }
290 if (!*y) {
291 return -1;
292 }
293 *y++ = '\0';
294 state->window_x = SDL_atoi(x);
295 state->window_y = SDL_atoi(y);
296 return 2;
297 }
298 if (SDL_strcasecmp(argv[index], "--usable-bounds") == 0) {
299 /* !!! FIXME: this is a bit of a hack, but I don't want to add a
300 !!! FIXME: flag to the public structure in 2.0.x */
301 state->window_x = -1;
302 state->window_y = -1;
303 state->window_w = -1;
304 state->window_h = -1;
305 return 1;
306 }
307 if (SDL_strcasecmp(argv[index], "--geometry") == 0) {
308 char *w, *h;
309 ++index;
310 if (!argv[index]) {
311 return -1;
312 }
313 w = argv[index];
314 h = argv[index];
315 while (*h && *h != 'x') {
316 ++h;
317 }
318 if (!*h) {
319 return -1;
320 }
321 *h++ = '\0';
322 state->window_w = SDL_atoi(w);
323 state->window_h = SDL_atoi(h);
324 return 2;
325 }
326 if (SDL_strcasecmp(argv[index], "--min-geometry") == 0) {
327 char *w, *h;
328 ++index;
329 if (!argv[index]) {
330 return -1;
331 }
332 w = argv[index];
333 h = argv[index];
334 while (*h && *h != 'x') {
335 ++h;
336 }
337 if (!*h) {
338 return -1;
339 }
340 *h++ = '\0';
341 state->window_minW = SDL_atoi(w);
342 state->window_minH = SDL_atoi(h);
343 return 2;
344 }
345 if (SDL_strcasecmp(argv[index], "--max-geometry") == 0) {
346 char *w, *h;
347 ++index;
348 if (!argv[index]) {
349 return -1;
350 }
351 w = argv[index];
352 h = argv[index];
353 while (*h && *h != 'x') {
354 ++h;
355 }
356 if (!*h) {
357 return -1;
358 }
359 *h++ = '\0';
360 state->window_maxW = SDL_atoi(w);
361 state->window_maxH = SDL_atoi(h);
362 return 2;
363 }
364 if (SDL_strcasecmp(argv[index], "--logical") == 0) {
365 char *w, *h;
366 ++index;
367 if (!argv[index]) {
368 return -1;
369 }
370 w = argv[index];
371 h = argv[index];
372 while (*h && *h != 'x') {
373 ++h;
374 }
375 if (!*h) {
376 return -1;
377 }
378 *h++ = '\0';
379 state->logical_w = SDL_atoi(w);
380 state->logical_h = SDL_atoi(h);
381 return 2;
382 }
383 if (SDL_strcasecmp(argv[index], "--scale") == 0) {
384 ++index;
385 if (!argv[index]) {
386 return -1;
387 }
388 state->scale = (float)SDL_atof(argv[index]);
389 return 2;
390 }
391 if (SDL_strcasecmp(argv[index], "--depth") == 0) {
392 ++index;
393 if (!argv[index]) {
394 return -1;
395 }
396 state->depth = SDL_atoi(argv[index]);
397 return 2;
398 }
399 if (SDL_strcasecmp(argv[index], "--refresh") == 0) {
400 ++index;
401 if (!argv[index]) {
402 return -1;
403 }
404 state->refresh_rate = SDL_atoi(argv[index]);
405 return 2;
406 }
407 if (SDL_strcasecmp(argv[index], "--vsync") == 0) {
408 state->render_flags |= SDL_RENDERER_PRESENTVSYNC;
409 return 1;
410 }
411 if (SDL_strcasecmp(argv[index], "--noframe") == 0) {
412 state->window_flags |= SDL_WINDOW_BORDERLESS;
413 return 1;
414 }
415 if (SDL_strcasecmp(argv[index], "--resize") == 0) {
416 state->window_flags |= SDL_WINDOW_RESIZABLE;
417 return 1;
418 }
419 if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
420 state->window_flags |= SDL_WINDOW_MINIMIZED;
421 return 1;
422 }
423 if (SDL_strcasecmp(argv[index], "--maximize") == 0) {
424 state->window_flags |= SDL_WINDOW_MAXIMIZED;
425 return 1;
426 }
427 if (SDL_strcasecmp(argv[index], "--grab") == 0) {
428 state->window_flags |= SDL_WINDOW_MOUSE_GRABBED;
429 return 1;
430 }
431 if (SDL_strcasecmp(argv[index], "--keyboard-grab") == 0) {
432 state->window_flags |= SDL_WINDOW_KEYBOARD_GRABBED;
433 return 1;
434 }
435 if (SDL_strcasecmp(argv[index], "--rate") == 0) {
436 ++index;
437 if (!argv[index]) {
438 return -1;
439 }
440 state->audiospec.freq = SDL_atoi(argv[index]);
441 return 2;
442 }
443 if (SDL_strcasecmp(argv[index], "--format") == 0) {
444 ++index;
445 if (!argv[index]) {
446 return -1;
447 }
448 if (SDL_strcasecmp(argv[index], "U8") == 0) {
449 state->audiospec.format = AUDIO_U8;
450 return 2;
451 }
452 if (SDL_strcasecmp(argv[index], "S8") == 0) {
453 state->audiospec.format = AUDIO_S8;
454 return 2;
455 }
456 if (SDL_strcasecmp(argv[index], "U16") == 0) {
457 state->audiospec.format = AUDIO_U16;
458 return 2;
459 }
460 if (SDL_strcasecmp(argv[index], "U16LE") == 0) {
461 state->audiospec.format = AUDIO_U16LSB;
462 return 2;
463 }
464 if (SDL_strcasecmp(argv[index], "U16BE") == 0) {
465 state->audiospec.format = AUDIO_U16MSB;
466 return 2;
467 }
468 if (SDL_strcasecmp(argv[index], "S16") == 0) {
469 state->audiospec.format = AUDIO_S16;
470 return 2;
471 }
472 if (SDL_strcasecmp(argv[index], "S16LE") == 0) {
473 state->audiospec.format = AUDIO_S16LSB;
474 return 2;
475 }
476 if (SDL_strcasecmp(argv[index], "S16BE") == 0) {
477 state->audiospec.format = AUDIO_S16MSB;
478 return 2;
479 }
480 return -1;
481 }
482 if (SDL_strcasecmp(argv[index], "--channels") == 0) {
483 ++index;
484 if (!argv[index]) {
485 return -1;
486 }
487 state->audiospec.channels = (Uint8) SDL_atoi(argv[index]);
488 return 2;
489 }
490 if (SDL_strcasecmp(argv[index], "--samples") == 0) {
491 ++index;
492 if (!argv[index]) {
493 return -1;
494 }
495 state->audiospec.samples = (Uint16) SDL_atoi(argv[index]);
496 return 2;
497 }
498 if (SDL_strcasecmp(argv[index], "--trackmem") == 0) {
499 /* Already handled in SDLTest_CommonCreateState() */
500 return 1;
501 }
502 if ((SDL_strcasecmp(argv[index], "-h") == 0)
503 || (SDL_strcasecmp(argv[index], "--help") == 0)) {
504 /* Print the usage message */
505 return -1;
506 }
507 if (SDL_strcmp(argv[index], "-NSDocumentRevisionsDebugMode") == 0) {
508 /* Debug flag sent by Xcode */
509 return 2;
510 }
511 return 0;
512}
513
514void
515SDLTest_CommonLogUsage(SDLTest_CommonState * state, const char *argv0, const char **options)
516{
517 int i;
518
519 SDL_Log("USAGE: %s", argv0);
520 SDL_Log(" %s", "[--trackmem]");
521
522 if (state->flags & SDL_INIT_VIDEO) {
523 for (i = 0; i < SDL_arraysize(video_usage); i++) {
524 SDL_Log(" %s", video_usage[i]);
525 }
526 }
527
528 if (state->flags & SDL_INIT_AUDIO) {
529 for (i = 0; i < SDL_arraysize(audio_usage); i++) {
530 SDL_Log(" %s", audio_usage[i]);
531 }
532 }
533
534 if (options) {
535 for (i = 0; options[i] != NULL; i++) {
536 SDL_Log(" %s", options[i]);
537 }
538 }
539}
540
541static const char *
542BuildCommonUsageString(char **pstr, const char **strlist, const int numitems, const char **strlist2, const int numitems2)
543{
544 char *str = *pstr;
545 if (!str) {
546 size_t len = SDL_strlen("[--trackmem]") + 2;
547 int i;
548 for (i = 0; i < numitems; i++) {
549 len += SDL_strlen(strlist[i]) + 1;
550 }
551 if (strlist2) {
552 for (i = 0; i < numitems2; i++) {
553 len += SDL_strlen(strlist2[i]) + 1;
554 }
555 }
556 str = (char *) SDL_calloc(1, len);
557 if (!str) {
558 return ""; /* oh well. */
559 }
560 SDL_strlcat(str, "[--trackmem] ", len);
561 for (i = 0; i < numitems-1; i++) {
562 SDL_strlcat(str, strlist[i], len);
563 SDL_strlcat(str, " ", len);
564 }
565 SDL_strlcat(str, strlist[i], len);
566 if (strlist2) {
567 SDL_strlcat(str, " ", len);
568 for (i = 0; i < numitems2-1; i++) {
569 SDL_strlcat(str, strlist2[i], len);
570 SDL_strlcat(str, " ", len);
571 }
572 SDL_strlcat(str, strlist2[i], len);
573 }
574 *pstr = str;
575 }
576 return str;
577}
578
579static char *common_usage_video = NULL;
580static char *common_usage_audio = NULL;
581static char *common_usage_videoaudio = NULL;
582
583const char *
584SDLTest_CommonUsage(SDLTest_CommonState * state)
585{
586
587 switch (state->flags & (SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
588 case SDL_INIT_VIDEO:
589 return BuildCommonUsageString(&common_usage_video, video_usage, SDL_arraysize(video_usage), NULL, 0);
590 case SDL_INIT_AUDIO:
591 return BuildCommonUsageString(&common_usage_audio, audio_usage, SDL_arraysize(audio_usage), NULL, 0);
592 case (SDL_INIT_VIDEO | SDL_INIT_AUDIO):
593 return BuildCommonUsageString(&common_usage_videoaudio, video_usage, SDL_arraysize(video_usage), audio_usage, SDL_arraysize(audio_usage));
594 default:
595 return "[--trackmem]";
596 }
597}
598
599
600SDL_bool
601SDLTest_CommonDefaultArgs(SDLTest_CommonState *state, const int argc, char **argv)
602{
603 int i = 1;
604 while (i < argc) {
605 const int consumed = SDLTest_CommonArg(state, i);
606 if (consumed == 0) {
607 SDLTest_CommonLogUsage(state, argv[0], NULL);
608 return SDL_FALSE;
609 }
610 i += consumed;
611 }
612 return SDL_TRUE;
613}
614
615static void
616SDLTest_PrintRendererFlag(char *text, size_t maxlen, Uint32 flag)
617{
618 switch (flag) {
619 case SDL_RENDERER_SOFTWARE:
620 SDL_snprintfcat(text, maxlen, "Software");
621 break;
622 case SDL_RENDERER_ACCELERATED:
623 SDL_snprintfcat(text, maxlen, "Accelerated");
624 break;
625 case SDL_RENDERER_PRESENTVSYNC:
626 SDL_snprintfcat(text, maxlen, "PresentVSync");
627 break;
628 case SDL_RENDERER_TARGETTEXTURE:
629 SDL_snprintfcat(text, maxlen, "TargetTexturesSupported");
630 break;
631 default:
632 SDL_snprintfcat(text, maxlen, "0x%8.8x", flag);
633 break;
634 }
635}
636
637static void
638SDLTest_PrintPixelFormat(char *text, size_t maxlen, Uint32 format)
639{
640 switch (format) {
641 case SDL_PIXELFORMAT_UNKNOWN:
642 SDL_snprintfcat(text, maxlen, "Unknown");
643 break;
644 case SDL_PIXELFORMAT_INDEX1LSB:
645 SDL_snprintfcat(text, maxlen, "Index1LSB");
646 break;
647 case SDL_PIXELFORMAT_INDEX1MSB:
648 SDL_snprintfcat(text, maxlen, "Index1MSB");
649 break;
650 case SDL_PIXELFORMAT_INDEX4LSB:
651 SDL_snprintfcat(text, maxlen, "Index4LSB");
652 break;
653 case SDL_PIXELFORMAT_INDEX4MSB:
654 SDL_snprintfcat(text, maxlen, "Index4MSB");
655 break;
656 case SDL_PIXELFORMAT_INDEX8:
657 SDL_snprintfcat(text, maxlen, "Index8");
658 break;
659 case SDL_PIXELFORMAT_RGB332:
660 SDL_snprintfcat(text, maxlen, "RGB332");
661 break;
662 case SDL_PIXELFORMAT_RGB444:
663 SDL_snprintfcat(text, maxlen, "RGB444");
664 break;
665 case SDL_PIXELFORMAT_BGR444:
666 SDL_snprintfcat(text, maxlen, "BGR444");
667 break;
668 case SDL_PIXELFORMAT_RGB555:
669 SDL_snprintfcat(text, maxlen, "RGB555");
670 break;
671 case SDL_PIXELFORMAT_BGR555:
672 SDL_snprintfcat(text, maxlen, "BGR555");
673 break;
674 case SDL_PIXELFORMAT_ARGB4444:
675 SDL_snprintfcat(text, maxlen, "ARGB4444");
676 break;
677 case SDL_PIXELFORMAT_ABGR4444:
678 SDL_snprintfcat(text, maxlen, "ABGR4444");
679 break;
680 case SDL_PIXELFORMAT_ARGB1555:
681 SDL_snprintfcat(text, maxlen, "ARGB1555");
682 break;
683 case SDL_PIXELFORMAT_ABGR1555:
684 SDL_snprintfcat(text, maxlen, "ABGR1555");
685 break;
686 case SDL_PIXELFORMAT_RGB565:
687 SDL_snprintfcat(text, maxlen, "RGB565");
688 break;
689 case SDL_PIXELFORMAT_BGR565:
690 SDL_snprintfcat(text, maxlen, "BGR565");
691 break;
692 case SDL_PIXELFORMAT_RGB24:
693 SDL_snprintfcat(text, maxlen, "RGB24");
694 break;
695 case SDL_PIXELFORMAT_BGR24:
696 SDL_snprintfcat(text, maxlen, "BGR24");
697 break;
698 case SDL_PIXELFORMAT_RGB888:
699 SDL_snprintfcat(text, maxlen, "RGB888");
700 break;
701 case SDL_PIXELFORMAT_BGR888:
702 SDL_snprintfcat(text, maxlen, "BGR888");
703 break;
704 case SDL_PIXELFORMAT_ARGB8888:
705 SDL_snprintfcat(text, maxlen, "ARGB8888");
706 break;
707 case SDL_PIXELFORMAT_RGBA8888:
708 SDL_snprintfcat(text, maxlen, "RGBA8888");
709 break;
710 case SDL_PIXELFORMAT_ABGR8888:
711 SDL_snprintfcat(text, maxlen, "ABGR8888");
712 break;
713 case SDL_PIXELFORMAT_BGRA8888:
714 SDL_snprintfcat(text, maxlen, "BGRA8888");
715 break;
716 case SDL_PIXELFORMAT_ARGB2101010:
717 SDL_snprintfcat(text, maxlen, "ARGB2101010");
718 break;
719 case SDL_PIXELFORMAT_YV12:
720 SDL_snprintfcat(text, maxlen, "YV12");
721 break;
722 case SDL_PIXELFORMAT_IYUV:
723 SDL_snprintfcat(text, maxlen, "IYUV");
724 break;
725 case SDL_PIXELFORMAT_YUY2:
726 SDL_snprintfcat(text, maxlen, "YUY2");
727 break;
728 case SDL_PIXELFORMAT_UYVY:
729 SDL_snprintfcat(text, maxlen, "UYVY");
730 break;
731 case SDL_PIXELFORMAT_YVYU:
732 SDL_snprintfcat(text, maxlen, "YVYU");
733 break;
734 case SDL_PIXELFORMAT_NV12:
735 SDL_snprintfcat(text, maxlen, "NV12");
736 break;
737 case SDL_PIXELFORMAT_NV21:
738 SDL_snprintfcat(text, maxlen, "NV21");
739 break;
740 default:
741 SDL_snprintfcat(text, maxlen, "0x%8.8x", format);
742 break;
743 }
744}
745
746static void
747SDLTest_PrintRenderer(SDL_RendererInfo * info)
748{
749 int i, count;
750 char text[1024];
751
752 SDL_Log(" Renderer %s:\n", info->name);
753
754 SDL_snprintf(text, sizeof(text), " Flags: 0x%8.8" SDL_PRIX32, info->flags);
755 SDL_snprintfcat(text, sizeof(text), " (");
756 count = 0;
757 for (i = 0; i < sizeof(info->flags) * 8; ++i) {
758 Uint32 flag = (1 << i);
759 if (info->flags & flag) {
760 if (count > 0) {
761 SDL_snprintfcat(text, sizeof(text), " | ");
762 }
763 SDLTest_PrintRendererFlag(text, sizeof(text), flag);
764 ++count;
765 }
766 }
767 SDL_snprintfcat(text, sizeof(text), ")");
768 SDL_Log("%s\n", text);
769
770 SDL_snprintf(text, sizeof(text), " Texture formats (%" SDL_PRIu32 "): ", info->num_texture_formats);
771 for (i = 0; i < (int) info->num_texture_formats; ++i) {
772 if (i > 0) {
773 SDL_snprintfcat(text, sizeof(text), ", ");
774 }
775 SDLTest_PrintPixelFormat(text, sizeof(text), info->texture_formats[i]);
776 }
777 SDL_Log("%s\n", text);
778
779 if (info->max_texture_width || info->max_texture_height) {
780 SDL_Log(" Max Texture Size: %dx%d\n",
781 info->max_texture_width, info->max_texture_height);
782 }
783}
784
785static SDL_Surface *
786SDLTest_LoadIcon(const char *file)
787{
788 SDL_Surface *icon;
789
790 /* Load the icon surface */
791 icon = SDL_LoadBMP(file);
792 if (icon == NULL) {
793 SDL_Log("Couldn't load %s: %s\n", file, SDL_GetError());
794 return (NULL);
795 }
796
797 if (icon->format->palette) {
798 /* Set the colorkey */
799 SDL_SetColorKey(icon, 1, *((Uint8 *) icon->pixels));
800 }
801
802 return (icon);
803}
804
805static SDL_HitTestResult SDLCALL
806SDLTest_ExampleHitTestCallback(SDL_Window *win, const SDL_Point *area, void *data)
807{
808 int w, h;
809 const int RESIZE_BORDER = 8;
810 const int DRAGGABLE_TITLE = 32;
811
812 /*SDL_Log("Hit test point %d,%d\n", area->x, area->y);*/
813
814 SDL_GetWindowSize(win, &w, &h);
815
816 if (area->x < RESIZE_BORDER) {
817 if (area->y < RESIZE_BORDER) {
818 SDL_Log("SDL_HITTEST_RESIZE_TOPLEFT\n");
819 return SDL_HITTEST_RESIZE_TOPLEFT;
820 } else if (area->y >= (h-RESIZE_BORDER)) {
821 SDL_Log("SDL_HITTEST_RESIZE_BOTTOMLEFT\n");
822 return SDL_HITTEST_RESIZE_BOTTOMLEFT;
823 } else {
824 SDL_Log("SDL_HITTEST_RESIZE_LEFT\n");
825 return SDL_HITTEST_RESIZE_LEFT;
826 }
827 } else if (area->x >= (w-RESIZE_BORDER)) {
828 if (area->y < RESIZE_BORDER) {
829 SDL_Log("SDL_HITTEST_RESIZE_TOPRIGHT\n");
830 return SDL_HITTEST_RESIZE_TOPRIGHT;
831 } else if (area->y >= (h-RESIZE_BORDER)) {
832 SDL_Log("SDL_HITTEST_RESIZE_BOTTOMRIGHT\n");
833 return SDL_HITTEST_RESIZE_BOTTOMRIGHT;
834 } else {
835 SDL_Log("SDL_HITTEST_RESIZE_RIGHT\n");
836 return SDL_HITTEST_RESIZE_RIGHT;
837 }
838 } else if (area->y >= (h-RESIZE_BORDER)) {
839 SDL_Log("SDL_HITTEST_RESIZE_BOTTOM\n");
840 return SDL_HITTEST_RESIZE_BOTTOM;
841 } else if (area->y < RESIZE_BORDER) {
842 SDL_Log("SDL_HITTEST_RESIZE_TOP\n");
843 return SDL_HITTEST_RESIZE_TOP;
844 } else if (area->y < DRAGGABLE_TITLE) {
845 SDL_Log("SDL_HITTEST_DRAGGABLE\n");
846 return SDL_HITTEST_DRAGGABLE;
847 }
848 return SDL_HITTEST_NORMAL;
849}
850
851SDL_bool
852SDLTest_CommonInit(SDLTest_CommonState * state)
853{
854 int i, j, m, n, w, h;
855 SDL_DisplayMode fullscreen_mode;
856 char text[1024];
857
858 if (state->flags & SDL_INIT_VIDEO) {
859 if (state->verbose & VERBOSE_VIDEO) {
860 n = SDL_GetNumVideoDrivers();
861 if (n == 0) {
862 SDL_Log("No built-in video drivers\n");
863 } else {
864 SDL_snprintf(text, sizeof(text), "Built-in video drivers:");
865 for (i = 0; i < n; ++i) {
866 if (i > 0) {
867 SDL_snprintfcat(text, sizeof(text), ",");
868 }
869 SDL_snprintfcat(text, sizeof(text), " %s", SDL_GetVideoDriver(i));
870 }
871 SDL_Log("%s\n", text);
872 }
873 }
874 if (SDL_VideoInit(state->videodriver) < 0) {
875 SDL_Log("Couldn't initialize video driver: %s\n",
876 SDL_GetError());
877 return SDL_FALSE;
878 }
879 if (state->verbose & VERBOSE_VIDEO) {
880 SDL_Log("Video driver: %s\n",
881 SDL_GetCurrentVideoDriver());
882 }
883
884 /* Upload GL settings */
885 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, state->gl_red_size);
886 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, state->gl_green_size);
887 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, state->gl_blue_size);
888 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, state->gl_alpha_size);
889 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, state->gl_double_buffer);
890 SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, state->gl_buffer_size);
891 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, state->gl_depth_size);
892 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, state->gl_stencil_size);
893 SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, state->gl_accum_red_size);
894 SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, state->gl_accum_green_size);
895 SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, state->gl_accum_blue_size);
896 SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, state->gl_accum_alpha_size);
897 SDL_GL_SetAttribute(SDL_GL_STEREO, state->gl_stereo);
898 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, state->gl_multisamplebuffers);
899 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, state->gl_multisamplesamples);
900 if (state->gl_accelerated >= 0) {
901 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,
902 state->gl_accelerated);
903 }
904 SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, state->gl_retained_backing);
905 if (state->gl_major_version) {
906 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, state->gl_major_version);
907 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, state->gl_minor_version);
908 }
909 if (state->gl_debug) {
910 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
911 }
912 if (state->gl_profile_mask) {
913 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, state->gl_profile_mask);
914 }
915
916 if (state->verbose & VERBOSE_MODES) {
917 SDL_Rect bounds, usablebounds;
918 float hdpi = 0;
919 float vdpi = 0;
920 SDL_DisplayMode mode;
921 int bpp;
922 Uint32 Rmask, Gmask, Bmask, Amask;
923#if SDL_VIDEO_DRIVER_WINDOWS
924 int adapterIndex = 0;
925 int outputIndex = 0;
926#endif
927 n = SDL_GetNumVideoDisplays();
928 SDL_Log("Number of displays: %d\n", n);
929 for (i = 0; i < n; ++i) {
930 SDL_Log("Display %d: %s\n", i, SDL_GetDisplayName(i));
931
932 SDL_zero(bounds);
933 SDL_GetDisplayBounds(i, &bounds);
934
935 SDL_zero(usablebounds);
936 SDL_GetDisplayUsableBounds(i, &usablebounds);
937
938 SDL_GetDisplayDPI(i, NULL, &hdpi, &vdpi);
939
940 SDL_Log("Bounds: %dx%d at %d,%d\n", bounds.w, bounds.h, bounds.x, bounds.y);
941 SDL_Log("Usable bounds: %dx%d at %d,%d\n", usablebounds.w, usablebounds.h, usablebounds.x, usablebounds.y);
942 SDL_Log("DPI: %fx%f\n", hdpi, vdpi);
943
944 SDL_GetDesktopDisplayMode(i, &mode);
945 SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask, &Gmask,
946 &Bmask, &Amask);
947 SDL_Log(" Current mode: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
948 mode.w, mode.h, mode.refresh_rate, bpp,
949 SDL_GetPixelFormatName(mode.format));
950 if (Rmask || Gmask || Bmask) {
951 SDL_Log(" Red Mask = 0x%.8" SDL_PRIx32 "\n", Rmask);
952 SDL_Log(" Green Mask = 0x%.8" SDL_PRIx32 "\n", Gmask);
953 SDL_Log(" Blue Mask = 0x%.8" SDL_PRIx32 "\n", Bmask);
954 if (Amask)
955 SDL_Log(" Alpha Mask = 0x%.8" SDL_PRIx32 "\n", Amask);
956 }
957
958 /* Print available fullscreen video modes */
959 m = SDL_GetNumDisplayModes(i);
960 if (m == 0) {
961 SDL_Log("No available fullscreen video modes\n");
962 } else {
963 SDL_Log(" Fullscreen video modes:\n");
964 for (j = 0; j < m; ++j) {
965 SDL_GetDisplayMode(i, j, &mode);
966 SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask,
967 &Gmask, &Bmask, &Amask);
968 SDL_Log(" Mode %d: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
969 j, mode.w, mode.h, mode.refresh_rate, bpp,
970 SDL_GetPixelFormatName(mode.format));
971 if (Rmask || Gmask || Bmask) {
972 SDL_Log(" Red Mask = 0x%.8" SDL_PRIx32 "\n",
973 Rmask);
974 SDL_Log(" Green Mask = 0x%.8" SDL_PRIx32 "\n",
975 Gmask);
976 SDL_Log(" Blue Mask = 0x%.8" SDL_PRIx32 "\n",
977 Bmask);
978 if (Amask)
979 SDL_Log(" Alpha Mask = 0x%.8" SDL_PRIx32 "\n",
980 Amask);
981 }
982 }
983 }
984
985#if SDL_VIDEO_DRIVER_WINDOWS
986 /* Print the D3D9 adapter index */
987 adapterIndex = SDL_Direct3D9GetAdapterIndex( i );
988 SDL_Log("D3D9 Adapter Index: %d", adapterIndex);
989
990 /* Print the DXGI adapter and output indices */
991 SDL_DXGIGetOutputInfo(i, &adapterIndex, &outputIndex);
992 SDL_Log("DXGI Adapter Index: %d Output Index: %d", adapterIndex, outputIndex);
993#endif
994 }
995 }
996
997 if (state->verbose & VERBOSE_RENDER) {
998 SDL_RendererInfo info;
999
1000 n = SDL_GetNumRenderDrivers();
1001 if (n == 0) {
1002 SDL_Log("No built-in render drivers\n");
1003 } else {
1004 SDL_Log("Built-in render drivers:\n");
1005 for (i = 0; i < n; ++i) {
1006 SDL_GetRenderDriverInfo(i, &info);
1007 SDLTest_PrintRenderer(&info);
1008 }
1009 }
1010 }
1011
1012 SDL_zero(fullscreen_mode);
1013 switch (state->depth) {
1014 case 8:
1015 fullscreen_mode.format = SDL_PIXELFORMAT_INDEX8;
1016 break;
1017 case 15:
1018 fullscreen_mode.format = SDL_PIXELFORMAT_RGB555;
1019 break;
1020 case 16:
1021 fullscreen_mode.format = SDL_PIXELFORMAT_RGB565;
1022 break;
1023 case 24:
1024 fullscreen_mode.format = SDL_PIXELFORMAT_RGB24;
1025 break;
1026 default:
1027 fullscreen_mode.format = SDL_PIXELFORMAT_RGB888;
1028 break;
1029 }
1030 fullscreen_mode.refresh_rate = state->refresh_rate;
1031
1032 state->windows =
1033 (SDL_Window **) SDL_calloc(state->num_windows,
1034 sizeof(*state->windows));
1035 state->renderers =
1036 (SDL_Renderer **) SDL_calloc(state->num_windows,
1037 sizeof(*state->renderers));
1038 state->targets =
1039 (SDL_Texture **) SDL_calloc(state->num_windows,
1040 sizeof(*state->targets));
1041 if (!state->windows || !state->renderers) {
1042 SDL_Log("Out of memory!\n");
1043 return SDL_FALSE;
1044 }
1045 for (i = 0; i < state->num_windows; ++i) {
1046 char title[1024];
1047 SDL_Rect r;
1048
1049 r.x = state->window_x;
1050 r.y = state->window_y;
1051 r.w = state->window_w;
1052 r.h = state->window_h;
1053
1054 /* !!! FIXME: hack to make --usable-bounds work for now. */
1055 if ((r.x == -1) && (r.y == -1) && (r.w == -1) && (r.h == -1)) {
1056 SDL_GetDisplayUsableBounds(state->display, &r);
1057 }
1058
1059 if (state->num_windows > 1) {
1060 SDL_snprintf(title, SDL_arraysize(title), "%s %d",
1061 state->window_title, i + 1);
1062 } else {
1063 SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
1064 }
1065 state->windows[i] =
1066 SDL_CreateWindow(title, r.x, r.y, r.w, r.h, state->window_flags);
1067 if (!state->windows[i]) {
1068 SDL_Log("Couldn't create window: %s\n",
1069 SDL_GetError());
1070 return SDL_FALSE;
1071 }
1072 if (state->window_minW || state->window_minH) {
1073 SDL_SetWindowMinimumSize(state->windows[i], state->window_minW, state->window_minH);
1074 }
1075 if (state->window_maxW || state->window_maxH) {
1076 SDL_SetWindowMaximumSize(state->windows[i], state->window_maxW, state->window_maxH);
1077 }
1078 SDL_GetWindowSize(state->windows[i], &w, &h);
1079 if (!(state->window_flags & SDL_WINDOW_RESIZABLE) &&
1080 (w != state->window_w || h != state->window_h)) {
1081 printf("Window requested size %dx%d, got %dx%d\n", state->window_w, state->window_h, w, h);
1082 state->window_w = w;
1083 state->window_h = h;
1084 }
1085 if (SDL_SetWindowDisplayMode(state->windows[i], &fullscreen_mode) < 0) {
1086 SDL_Log("Can't set up fullscreen display mode: %s\n",
1087 SDL_GetError());
1088 return SDL_FALSE;
1089 }
1090
1091 /* Add resize/drag areas for windows that are borderless and resizable */
1092 if ((state->window_flags & (SDL_WINDOW_RESIZABLE|SDL_WINDOW_BORDERLESS)) ==
1093 (SDL_WINDOW_RESIZABLE|SDL_WINDOW_BORDERLESS)) {
1094 SDL_SetWindowHitTest(state->windows[i], SDLTest_ExampleHitTestCallback, NULL);
1095 }
1096
1097 if (state->window_icon) {
1098 SDL_Surface *icon = SDLTest_LoadIcon(state->window_icon);
1099 if (icon) {
1100 SDL_SetWindowIcon(state->windows[i], icon);
1101 SDL_FreeSurface(icon);
1102 }
1103 }
1104
1105 SDL_ShowWindow(state->windows[i]);
1106
1107 if (!state->skip_renderer
1108 && (state->renderdriver
1109 || !(state->window_flags & (SDL_WINDOW_OPENGL | SDL_WINDOW_VULKAN | SDL_WINDOW_METAL)))) {
1110 m = -1;
1111 if (state->renderdriver) {
1112 SDL_RendererInfo info;
1113 n = SDL_GetNumRenderDrivers();
1114 for (j = 0; j < n; ++j) {
1115 SDL_GetRenderDriverInfo(j, &info);
1116 if (SDL_strcasecmp(info.name, state->renderdriver) ==
1117 0) {
1118 m = j;
1119 break;
1120 }
1121 }
1122 if (m == -1) {
1123 SDL_Log("Couldn't find render driver named %s",
1124 state->renderdriver);
1125 return SDL_FALSE;
1126 }
1127 }
1128 state->renderers[i] = SDL_CreateRenderer(state->windows[i],
1129 m, state->render_flags);
1130 if (!state->renderers[i]) {
1131 SDL_Log("Couldn't create renderer: %s\n",
1132 SDL_GetError());
1133 return SDL_FALSE;
1134 }
1135 if (state->logical_w && state->logical_h) {
1136 SDL_RenderSetLogicalSize(state->renderers[i], state->logical_w, state->logical_h);
1137 } else if (state->scale != 0.) {
1138 SDL_RenderSetScale(state->renderers[i], state->scale, state->scale);
1139 }
1140 if (state->verbose & VERBOSE_RENDER) {
1141 SDL_RendererInfo info;
1142
1143 SDL_Log("Current renderer:\n");
1144 SDL_GetRendererInfo(state->renderers[i], &info);
1145 SDLTest_PrintRenderer(&info);
1146 }
1147 }
1148 }
1149 }
1150
1151 if (state->flags & SDL_INIT_AUDIO) {
1152 if (state->verbose & VERBOSE_AUDIO) {
1153 n = SDL_GetNumAudioDrivers();
1154 if (n == 0) {
1155 SDL_Log("No built-in audio drivers\n");
1156 } else {
1157 SDL_snprintf(text, sizeof(text), "Built-in audio drivers:");
1158 for (i = 0; i < n; ++i) {
1159 if (i > 0) {
1160 SDL_snprintfcat(text, sizeof(text), ",");
1161 }
1162 SDL_snprintfcat(text, sizeof(text), " %s", SDL_GetAudioDriver(i));
1163 }
1164 SDL_Log("%s\n", text);
1165 }
1166 }
1167 if (SDL_AudioInit(state->audiodriver) < 0) {
1168 SDL_Log("Couldn't initialize audio driver: %s\n",
1169 SDL_GetError());
1170 return SDL_FALSE;
1171 }
1172 if (state->verbose & VERBOSE_AUDIO) {
1173 SDL_Log("Audio driver: %s\n",
1174 SDL_GetCurrentAudioDriver());
1175 }
1176
1177 if (SDL_OpenAudio(&state->audiospec, NULL) < 0) {
1178 SDL_Log("Couldn't open audio: %s\n", SDL_GetError());
1179 return SDL_FALSE;
1180 }
1181 }
1182
1183 return SDL_TRUE;
1184}
1185
1186static const char *
1187DisplayOrientationName(int orientation)
1188{
1189 switch (orientation)
1190 {
1191#define CASE(X) case SDL_ORIENTATION_##X: return #X
1192 CASE(UNKNOWN);
1193 CASE(LANDSCAPE);
1194 CASE(LANDSCAPE_FLIPPED);
1195 CASE(PORTRAIT);
1196 CASE(PORTRAIT_FLIPPED);
1197#undef CASE
1198default: return "???";
1199 }
1200}
1201
1202static const char *
1203ControllerAxisName(const SDL_GameControllerAxis axis)
1204{
1205 switch (axis)
1206 {
1207#define AXIS_CASE(ax) case SDL_CONTROLLER_AXIS_##ax: return #ax
1208 AXIS_CASE(INVALID);
1209 AXIS_CASE(LEFTX);
1210 AXIS_CASE(LEFTY);
1211 AXIS_CASE(RIGHTX);
1212 AXIS_CASE(RIGHTY);
1213 AXIS_CASE(TRIGGERLEFT);
1214 AXIS_CASE(TRIGGERRIGHT);
1215#undef AXIS_CASE
1216default: return "???";
1217 }
1218}
1219
1220static const char *
1221ControllerButtonName(const SDL_GameControllerButton button)
1222{
1223 switch (button)
1224 {
1225#define BUTTON_CASE(btn) case SDL_CONTROLLER_BUTTON_##btn: return #btn
1226 BUTTON_CASE(INVALID);
1227 BUTTON_CASE(A);
1228 BUTTON_CASE(B);
1229 BUTTON_CASE(X);
1230 BUTTON_CASE(Y);
1231 BUTTON_CASE(BACK);
1232 BUTTON_CASE(GUIDE);
1233 BUTTON_CASE(START);
1234 BUTTON_CASE(LEFTSTICK);
1235 BUTTON_CASE(RIGHTSTICK);
1236 BUTTON_CASE(LEFTSHOULDER);
1237 BUTTON_CASE(RIGHTSHOULDER);
1238 BUTTON_CASE(DPAD_UP);
1239 BUTTON_CASE(DPAD_DOWN);
1240 BUTTON_CASE(DPAD_LEFT);
1241 BUTTON_CASE(DPAD_RIGHT);
1242#undef BUTTON_CASE
1243default: return "???";
1244 }
1245}
1246
1247static void
1248SDLTest_PrintEvent(SDL_Event * event)
1249{
1250 if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_FINGERMOTION)) {
1251 /* Mouse and finger motion are really spammy */
1252 return;
1253 }
1254
1255 switch (event->type) {
1256 case SDL_DISPLAYEVENT:
1257 switch (event->display.event) {
1258 case SDL_DISPLAYEVENT_ORIENTATION:
1259 SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " changed orientation to %s",
1260 event->display.display, DisplayOrientationName(event->display.data1));
1261 break;
1262 default:
1263 SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " got unknown event 0x%4.4x",
1264 event->display.display, event->display.event);
1265 break;
1266 }
1267 break;
1268 case SDL_WINDOWEVENT:
1269 switch (event->window.event) {
1270 case SDL_WINDOWEVENT_SHOWN:
1271 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " shown", event->window.windowID);
1272 break;
1273 case SDL_WINDOWEVENT_HIDDEN:
1274 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " hidden", event->window.windowID);
1275 break;
1276 case SDL_WINDOWEVENT_EXPOSED:
1277 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " exposed", event->window.windowID);
1278 break;
1279 case SDL_WINDOWEVENT_MOVED:
1280 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " moved to %" SDL_PRIs32 ",%" SDL_PRIs32,
1281 event->window.windowID, event->window.data1, event->window.data2);
1282 break;
1283 case SDL_WINDOWEVENT_RESIZED:
1284 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " resized to %" SDL_PRIs32 "x%" SDL_PRIs32,
1285 event->window.windowID, event->window.data1, event->window.data2);
1286 break;
1287 case SDL_WINDOWEVENT_SIZE_CHANGED:
1288 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " changed size to %" SDL_PRIs32 "x%" SDL_PRIs32,
1289 event->window.windowID, event->window.data1, event->window.data2);
1290 break;
1291 case SDL_WINDOWEVENT_MINIMIZED:
1292 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " minimized", event->window.windowID);
1293 break;
1294 case SDL_WINDOWEVENT_MAXIMIZED:
1295 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " maximized", event->window.windowID);
1296 break;
1297 case SDL_WINDOWEVENT_RESTORED:
1298 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " restored", event->window.windowID);
1299 break;
1300 case SDL_WINDOWEVENT_ENTER:
1301 SDL_Log("SDL EVENT: Mouse entered window %" SDL_PRIu32 "",
1302 event->window.windowID);
1303 break;
1304 case SDL_WINDOWEVENT_LEAVE:
1305 SDL_Log("SDL EVENT: Mouse left window %" SDL_PRIu32 "", event->window.windowID);
1306 break;
1307 case SDL_WINDOWEVENT_FOCUS_GAINED:
1308 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " gained keyboard focus",
1309 event->window.windowID);
1310 break;
1311 case SDL_WINDOWEVENT_FOCUS_LOST:
1312 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " lost keyboard focus",
1313 event->window.windowID);
1314 break;
1315 case SDL_WINDOWEVENT_CLOSE:
1316 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " closed", event->window.windowID);
1317 break;
1318 case SDL_WINDOWEVENT_TAKE_FOCUS:
1319 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " take focus", event->window.windowID);
1320 break;
1321 case SDL_WINDOWEVENT_HIT_TEST:
1322 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " hit test", event->window.windowID);
1323 break;
1324 default:
1325 SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " got unknown event 0x%4.4x",
1326 event->window.windowID, event->window.event);
1327 break;
1328 }
1329 break;
1330 case SDL_KEYDOWN:
1331 SDL_Log("SDL EVENT: Keyboard: key pressed in window %" SDL_PRIu32 ": scancode 0x%08X = %s, keycode 0x%08" SDL_PRIX32 " = %s",
1332 event->key.windowID,
1333 event->key.keysym.scancode,
1334 SDL_GetScancodeName(event->key.keysym.scancode),
1335 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
1336 break;
1337 case SDL_KEYUP:
1338 SDL_Log("SDL EVENT: Keyboard: key released in window %" SDL_PRIu32 ": scancode 0x%08X = %s, keycode 0x%08" SDL_PRIX32 " = %s",
1339 event->key.windowID,
1340 event->key.keysym.scancode,
1341 SDL_GetScancodeName(event->key.keysym.scancode),
1342 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
1343 break;
1344 case SDL_TEXTEDITING:
1345 SDL_Log("SDL EVENT: Keyboard: text editing \"%s\" in window %" SDL_PRIu32,
1346 event->edit.text, event->edit.windowID);
1347 break;
1348 case SDL_TEXTINPUT:
1349 SDL_Log("SDL EVENT: Keyboard: text input \"%s\" in window %" SDL_PRIu32,
1350 event->text.text, event->text.windowID);
1351 break;
1352 case SDL_KEYMAPCHANGED:
1353 SDL_Log("SDL EVENT: Keymap changed");
1354 break;
1355 case SDL_MOUSEMOTION:
1356 SDL_Log("SDL EVENT: Mouse: moved to %" SDL_PRIs32 ",%" SDL_PRIs32 " (%" SDL_PRIs32 ",%" SDL_PRIs32 ") in window %" SDL_PRIu32,
1357 event->motion.x, event->motion.y,
1358 event->motion.xrel, event->motion.yrel,
1359 event->motion.windowID);
1360 break;
1361 case SDL_MOUSEBUTTONDOWN:
1362 SDL_Log("SDL EVENT: Mouse: button %d pressed at %" SDL_PRIs32 ",%" SDL_PRIs32 " with click count %d in window %" SDL_PRIu32,
1363 event->button.button, event->button.x, event->button.y, event->button.clicks,
1364 event->button.windowID);
1365 break;
1366 case SDL_MOUSEBUTTONUP:
1367 SDL_Log("SDL EVENT: Mouse: button %d released at %" SDL_PRIs32 ",%" SDL_PRIs32 " with click count %d in window %" SDL_PRIu32,
1368 event->button.button, event->button.x, event->button.y, event->button.clicks,
1369 event->button.windowID);
1370 break;
1371 case SDL_MOUSEWHEEL:
1372 SDL_Log("SDL EVENT: Mouse: wheel scrolled %" SDL_PRIs32 " in x and %" SDL_PRIs32 " in y (reversed: %" SDL_PRIu32 ") in window %" SDL_PRIu32,
1373 event->wheel.x, event->wheel.y, event->wheel.direction, event->wheel.windowID);
1374 break;
1375 case SDL_JOYDEVICEADDED:
1376 SDL_Log("SDL EVENT: Joystick index %" SDL_PRIs32 " attached",
1377 event->jdevice.which);
1378 break;
1379 case SDL_JOYDEVICEREMOVED:
1380 SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 " removed",
1381 event->jdevice.which);
1382 break;
1383 case SDL_JOYBALLMOTION:
1384 SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 ": ball %d moved by %d,%d",
1385 event->jball.which, event->jball.ball, event->jball.xrel,
1386 event->jball.yrel);
1387 break;
1388 case SDL_JOYHATMOTION:
1389 {
1390 const char *position = "UNKNOWN";
1391 switch (event->jhat.value) {
1392 case SDL_HAT_CENTERED:
1393 position = "CENTER";
1394 break;
1395 case SDL_HAT_UP:
1396 position = "UP";
1397 break;
1398 case SDL_HAT_RIGHTUP:
1399 position = "RIGHTUP";
1400 break;
1401 case SDL_HAT_RIGHT:
1402 position = "RIGHT";
1403 break;
1404 case SDL_HAT_RIGHTDOWN:
1405 position = "RIGHTDOWN";
1406 break;
1407 case SDL_HAT_DOWN:
1408 position = "DOWN";
1409 break;
1410 case SDL_HAT_LEFTDOWN:
1411 position = "LEFTDOWN";
1412 break;
1413 case SDL_HAT_LEFT:
1414 position = "LEFT";
1415 break;
1416 case SDL_HAT_LEFTUP:
1417 position = "LEFTUP";
1418 break;
1419 }
1420 SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 ": hat %d moved to %s",
1421 event->jhat.which, event->jhat.hat, position);
1422 }
1423 break;
1424 case SDL_JOYBUTTONDOWN:
1425 SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 ": button %d pressed",
1426 event->jbutton.which, event->jbutton.button);
1427 break;
1428 case SDL_JOYBUTTONUP:
1429 SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 ": button %d released",
1430 event->jbutton.which, event->jbutton.button);
1431 break;
1432 case SDL_CONTROLLERDEVICEADDED:
1433 SDL_Log("SDL EVENT: Controller index %" SDL_PRIs32 " attached",
1434 event->cdevice.which);
1435 break;
1436 case SDL_CONTROLLERDEVICEREMOVED:
1437 SDL_Log("SDL EVENT: Controller %" SDL_PRIs32 " removed",
1438 event->cdevice.which);
1439 break;
1440 case SDL_CONTROLLERAXISMOTION:
1441 SDL_Log("SDL EVENT: Controller %" SDL_PRIs32 " axis %d ('%s') value: %d",
1442 event->caxis.which,
1443 event->caxis.axis,
1444 ControllerAxisName((SDL_GameControllerAxis)event->caxis.axis),
1445 event->caxis.value);
1446 break;
1447 case SDL_CONTROLLERBUTTONDOWN:
1448 SDL_Log("SDL EVENT: Controller %" SDL_PRIs32 "button %d ('%s') down",
1449 event->cbutton.which, event->cbutton.button,
1450 ControllerButtonName((SDL_GameControllerButton)event->cbutton.button));
1451 break;
1452 case SDL_CONTROLLERBUTTONUP:
1453 SDL_Log("SDL EVENT: Controller %" SDL_PRIs32 " button %d ('%s') up",
1454 event->cbutton.which, event->cbutton.button,
1455 ControllerButtonName((SDL_GameControllerButton)event->cbutton.button));
1456 break;
1457 case SDL_CLIPBOARDUPDATE:
1458 SDL_Log("SDL EVENT: Clipboard updated");
1459 break;
1460
1461 case SDL_FINGERMOTION:
1462 SDL_Log("SDL EVENT: Finger: motion touch=%ld, finger=%ld, x=%f, y=%f, dx=%f, dy=%f, pressure=%f",
1463 (long) event->tfinger.touchId,
1464 (long) event->tfinger.fingerId,
1465 event->tfinger.x, event->tfinger.y,
1466 event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
1467 break;
1468 case SDL_FINGERDOWN:
1469 case SDL_FINGERUP:
1470 SDL_Log("SDL EVENT: Finger: %s touch=%ld, finger=%ld, x=%f, y=%f, dx=%f, dy=%f, pressure=%f",
1471 (event->type == SDL_FINGERDOWN) ? "down" : "up",
1472 (long) event->tfinger.touchId,
1473 (long) event->tfinger.fingerId,
1474 event->tfinger.x, event->tfinger.y,
1475 event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
1476 break;
1477 case SDL_DOLLARGESTURE:
1478 SDL_Log("SDL_EVENT: Dollar gesture detect: %ld", (long) event->dgesture.gestureId);
1479 break;
1480 case SDL_DOLLARRECORD:
1481 SDL_Log("SDL_EVENT: Dollar gesture record: %ld", (long) event->dgesture.gestureId);
1482 break;
1483 case SDL_MULTIGESTURE:
1484 SDL_Log("SDL_EVENT: Multi gesture fingers: %d", event->mgesture.numFingers);
1485 break;
1486
1487 case SDL_RENDER_DEVICE_RESET:
1488 SDL_Log("SDL EVENT: render device reset");
1489 break;
1490 case SDL_RENDER_TARGETS_RESET:
1491 SDL_Log("SDL EVENT: render targets reset");
1492 break;
1493
1494 case SDL_APP_TERMINATING:
1495 SDL_Log("SDL EVENT: App terminating");
1496 break;
1497 case SDL_APP_LOWMEMORY:
1498 SDL_Log("SDL EVENT: App running low on memory");
1499 break;
1500 case SDL_APP_WILLENTERBACKGROUND:
1501 SDL_Log("SDL EVENT: App will enter the background");
1502 break;
1503 case SDL_APP_DIDENTERBACKGROUND:
1504 SDL_Log("SDL EVENT: App entered the background");
1505 break;
1506 case SDL_APP_WILLENTERFOREGROUND:
1507 SDL_Log("SDL EVENT: App will enter the foreground");
1508 break;
1509 case SDL_APP_DIDENTERFOREGROUND:
1510 SDL_Log("SDL EVENT: App entered the foreground");
1511 break;
1512 case SDL_DROPBEGIN:
1513 SDL_Log("SDL EVENT: Drag and drop beginning");
1514 break;
1515 case SDL_DROPFILE:
1516 SDL_Log("SDL EVENT: Drag and drop file: '%s'", event->drop.file);
1517 break;
1518 case SDL_DROPTEXT:
1519 SDL_Log("SDL EVENT: Drag and drop text: '%s'", event->drop.file);
1520 break;
1521 case SDL_DROPCOMPLETE:
1522 SDL_Log("SDL EVENT: Drag and drop ending");
1523 break;
1524 case SDL_QUIT:
1525 SDL_Log("SDL EVENT: Quit requested");
1526 break;
1527 case SDL_USEREVENT:
1528 SDL_Log("SDL EVENT: User event %" SDL_PRIs32, event->user.code);
1529 break;
1530 default:
1531 SDL_Log("Unknown event 0x%4.4" SDL_PRIu32, event->type);
1532 break;
1533 }
1534}
1535
1536static void
1537SDLTest_ScreenShot(SDL_Renderer *renderer)
1538{
1539 SDL_Rect viewport;
1540 SDL_Surface *surface;
1541
1542 if (!renderer) {
1543 return;
1544 }
1545
1546 SDL_RenderGetViewport(renderer, &viewport);
1547 surface = SDL_CreateRGBSurface(0, viewport.w, viewport.h, 24,
1548#if SDL_BYTEORDER == SDL_LIL_ENDIAN
1549 0x00FF0000, 0x0000FF00, 0x000000FF,
1550#else
1551 0x000000FF, 0x0000FF00, 0x00FF0000,
1552#endif
1553 0x00000000);
1554 if (!surface) {
1555 SDL_Log("Couldn't create surface: %s\n", SDL_GetError());
1556 return;
1557 }
1558
1559 if (SDL_RenderReadPixels(renderer, NULL, surface->format->format,
1560 surface->pixels, surface->pitch) < 0) {
1561 SDL_Log("Couldn't read screen: %s\n", SDL_GetError());
1562 SDL_free(surface);
1563 return;
1564 }
1565
1566 if (SDL_SaveBMP(surface, "screenshot.bmp") < 0) {
1567 SDL_Log("Couldn't save screenshot.bmp: %s\n", SDL_GetError());
1568 SDL_free(surface);
1569 return;
1570 }
1571}
1572
1573static void
1574FullscreenTo(int index, int windowId)
1575{
1576 Uint32 flags;
1577 struct SDL_Rect rect = { 0, 0, 0, 0 };
1578 SDL_Window *window = SDL_GetWindowFromID(windowId);
1579 if (!window) {
1580 return;
1581 }
1582
1583 SDL_GetDisplayBounds( index, &rect );
1584
1585 flags = SDL_GetWindowFlags(window);
1586 if (flags & SDL_WINDOW_FULLSCREEN) {
1587 SDL_SetWindowFullscreen( window, SDL_FALSE );
1588 SDL_Delay( 15 );
1589 }
1590
1591 SDL_SetWindowPosition( window, rect.x, rect.y );
1592 SDL_SetWindowFullscreen( window, SDL_TRUE );
1593}
1594
1595void
1596SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
1597{
1598 int i;
1599 static SDL_MouseMotionEvent lastEvent;
1600
1601 if (state->verbose & VERBOSE_EVENT) {
1602 SDLTest_PrintEvent(event);
1603 }
1604
1605 switch (event->type) {
1606 case SDL_WINDOWEVENT:
1607 switch (event->window.event) {
1608 case SDL_WINDOWEVENT_CLOSE:
1609 {
1610 SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
1611 if (window) {
1612 for (i = 0; i < state->num_windows; ++i) {
1613 if (window == state->windows[i]) {
1614 if (state->targets[i]) {
1615 SDL_DestroyTexture(state->targets[i]);
1616 state->targets[i] = NULL;
1617 }
1618 if (state->renderers[i]) {
1619 SDL_DestroyRenderer(state->renderers[i]);
1620 state->renderers[i] = NULL;
1621 }
1622 SDL_DestroyWindow(state->windows[i]);
1623 state->windows[i] = NULL;
1624 break;
1625 }
1626 }
1627 }
1628 }
1629 break;
1630 }
1631 break;
1632 case SDL_KEYDOWN: {
1633 SDL_bool withControl = !!(event->key.keysym.mod & KMOD_CTRL);
1634 SDL_bool withShift = !!(event->key.keysym.mod & KMOD_SHIFT);
1635 SDL_bool withAlt = !!(event->key.keysym.mod & KMOD_ALT);
1636
1637 switch (event->key.keysym.sym) {
1638 /* Add hotkeys here */
1639 case SDLK_PRINTSCREEN: {
1640 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1641 if (window) {
1642 for (i = 0; i < state->num_windows; ++i) {
1643 if (window == state->windows[i]) {
1644 SDLTest_ScreenShot(state->renderers[i]);
1645 }
1646 }
1647 }
1648 }
1649 break;
1650 case SDLK_EQUALS:
1651 if (withControl) {
1652 /* Ctrl-+ double the size of the window */
1653 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1654 if (window) {
1655 int w, h;
1656 SDL_GetWindowSize(window, &w, &h);
1657 SDL_SetWindowSize(window, w*2, h*2);
1658 }
1659 }
1660 break;
1661 case SDLK_MINUS:
1662 if (withControl) {
1663 /* Ctrl-- half the size of the window */
1664 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1665 if (window) {
1666 int w, h;
1667 SDL_GetWindowSize(window, &w, &h);
1668 SDL_SetWindowSize(window, w/2, h/2);
1669 }
1670 }
1671 break;
1672 case SDLK_UP:
1673 case SDLK_DOWN:
1674 case SDLK_LEFT:
1675 case SDLK_RIGHT:
1676 if (withAlt) {
1677 /* Alt-Up/Down/Left/Right switches between displays */
1678 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1679 if (window) {
1680 int currentIndex = SDL_GetWindowDisplayIndex(window);
1681 int numDisplays = SDL_GetNumVideoDisplays();
1682
1683 if (currentIndex >= 0 && numDisplays >= 1) {
1684 int dest;
1685 if (event->key.keysym.sym == SDLK_UP || event->key.keysym.sym == SDLK_LEFT) {
1686 dest = (currentIndex + numDisplays - 1) % numDisplays;
1687 } else {
1688 dest = (currentIndex + numDisplays + 1) % numDisplays;
1689 }
1690 SDL_Log("Centering on display %d\n", dest);
1691 SDL_SetWindowPosition(window,
1692 SDL_WINDOWPOS_CENTERED_DISPLAY(dest),
1693 SDL_WINDOWPOS_CENTERED_DISPLAY(dest));
1694 }
1695 }
1696 }
1697 if (withShift) {
1698 /* Shift-Up/Down/Left/Right shift the window by 100px */
1699 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1700 if (window) {
1701 const int delta = 100;
1702 int x, y;
1703 SDL_GetWindowPosition(window, &x, &y);
1704
1705 if (event->key.keysym.sym == SDLK_UP) y -= delta;
1706 if (event->key.keysym.sym == SDLK_DOWN) y += delta;
1707 if (event->key.keysym.sym == SDLK_LEFT) x -= delta;
1708 if (event->key.keysym.sym == SDLK_RIGHT) x += delta;
1709
1710 SDL_Log("Setting position to (%d, %d)\n", x, y);
1711 SDL_SetWindowPosition(window, x, y);
1712 }
1713 }
1714 break;
1715 case SDLK_o:
1716 if (withControl) {
1717 /* Ctrl-O (or Ctrl-Shift-O) changes window opacity. */
1718 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1719 if (window) {
1720 float opacity;
1721 if (SDL_GetWindowOpacity(window, &opacity) == 0) {
1722 if (withShift) {
1723 opacity += 0.20f;
1724 } else {
1725 opacity -= 0.20f;
1726 }
1727 SDL_SetWindowOpacity(window, opacity);
1728 }
1729 }
1730 }
1731 break;
1732
1733 case SDLK_c:
1734 if (withControl) {
1735 /* Ctrl-C copy awesome text! */
1736 SDL_SetClipboardText("SDL rocks!\nYou know it!");
1737 printf("Copied text to clipboard\n");
1738 }
1739 if (withAlt) {
1740 /* Alt-C toggle a render clip rectangle */
1741 for (i = 0; i < state->num_windows; ++i) {
1742 int w, h;
1743 if (state->renderers[i]) {
1744 SDL_Rect clip;
1745 SDL_GetWindowSize(state->windows[i], &w, &h);
1746 SDL_RenderGetClipRect(state->renderers[i], &clip);
1747 if (SDL_RectEmpty(&clip)) {
1748 clip.x = w/4;
1749 clip.y = h/4;
1750 clip.w = w/2;
1751 clip.h = h/2;
1752 SDL_RenderSetClipRect(state->renderers[i], &clip);
1753 } else {
1754 SDL_RenderSetClipRect(state->renderers[i], NULL);
1755 }
1756 }
1757 }
1758 }
1759 if (withShift) {
1760 SDL_Window *current_win = SDL_GetKeyboardFocus();
1761 if (current_win) {
1762 const SDL_bool shouldCapture = (SDL_GetWindowFlags(current_win) & SDL_WINDOW_MOUSE_CAPTURE) == 0;
1763 const int rc = SDL_CaptureMouse(shouldCapture);
1764 SDL_Log("%sapturing mouse %s!\n", shouldCapture ? "C" : "Unc", (rc == 0) ? "succeeded" : "failed");
1765 }
1766 }
1767 break;
1768 case SDLK_v:
1769 if (withControl) {
1770 /* Ctrl-V paste awesome text! */
1771 char *text = SDL_GetClipboardText();
1772 if (*text) {
1773 printf("Clipboard: %s\n", text);
1774 } else {
1775 printf("Clipboard is empty\n");
1776 }
1777 SDL_free(text);
1778 }
1779 break;
1780 case SDLK_g:
1781 if (withControl) {
1782 /* Ctrl-G toggle mouse grab */
1783 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1784 if (window) {
1785 SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window) ? SDL_TRUE : SDL_FALSE);
1786 }
1787 }
1788 break;
1789 case SDLK_k:
1790 if (withControl) {
1791 /* Ctrl-K toggle keyboard grab */
1792 SDL_Window* window = SDL_GetWindowFromID(event->key.windowID);
1793 if (window) {
1794 SDL_SetWindowKeyboardGrab(window, !SDL_GetWindowKeyboardGrab(window) ? SDL_TRUE : SDL_FALSE);
1795 }
1796 }
1797 break;
1798 case SDLK_m:
1799 if (withControl) {
1800 /* Ctrl-M maximize */
1801 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1802 if (window) {
1803 Uint32 flags = SDL_GetWindowFlags(window);
1804 if (flags & SDL_WINDOW_MAXIMIZED) {
1805 SDL_RestoreWindow(window);
1806 } else {
1807 SDL_MaximizeWindow(window);
1808 }
1809 }
1810 }
1811 break;
1812 case SDLK_r:
1813 if (withControl) {
1814 /* Ctrl-R toggle mouse relative mode */
1815 SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode() ? SDL_TRUE : SDL_FALSE);
1816 }
1817 break;
1818 case SDLK_z:
1819 if (withControl) {
1820 /* Ctrl-Z minimize */
1821 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1822 if (window) {
1823 SDL_MinimizeWindow(window);
1824 }
1825 }
1826 break;
1827 case SDLK_RETURN:
1828 if (withControl) {
1829 /* Ctrl-Enter toggle fullscreen */
1830 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1831 if (window) {
1832 Uint32 flags = SDL_GetWindowFlags(window);
1833 if (flags & SDL_WINDOW_FULLSCREEN) {
1834 SDL_SetWindowFullscreen(window, SDL_FALSE);
1835 } else {
1836 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
1837 }
1838 }
1839 } else if (withAlt) {
1840 /* Alt-Enter toggle fullscreen desktop */
1841 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1842 if (window) {
1843 Uint32 flags = SDL_GetWindowFlags(window);
1844 if (flags & SDL_WINDOW_FULLSCREEN) {
1845 SDL_SetWindowFullscreen(window, SDL_FALSE);
1846 } else {
1847 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1848 }
1849 }
1850 } else if (withShift) {
1851 /* Shift-Enter toggle fullscreen desktop / fullscreen */
1852 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1853 if (window) {
1854 Uint32 flags = SDL_GetWindowFlags(window);
1855 if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
1856 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
1857 } else {
1858 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1859 }
1860 }
1861 }
1862
1863 break;
1864 case SDLK_b:
1865 if (withControl) {
1866 /* Ctrl-B toggle window border */
1867 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1868 if (window) {
1869 const Uint32 flags = SDL_GetWindowFlags(window);
1870 const SDL_bool b = ((flags & SDL_WINDOW_BORDERLESS) != 0) ? SDL_TRUE : SDL_FALSE;
1871 SDL_SetWindowBordered(window, b);
1872 }
1873 }
1874 break;
1875 case SDLK_a:
1876 if (withControl) {
1877 /* Ctrl-A reports absolute mouse position. */
1878 int x, y;
1879 const Uint32 mask = SDL_GetGlobalMouseState(&x, &y);
1880 SDL_Log("ABSOLUTE MOUSE: (%d, %d)%s%s%s%s%s\n", x, y,
1881 (mask & SDL_BUTTON_LMASK) ? " [LBUTTON]" : "",
1882 (mask & SDL_BUTTON_MMASK) ? " [MBUTTON]" : "",
1883 (mask & SDL_BUTTON_RMASK) ? " [RBUTTON]" : "",
1884 (mask & SDL_BUTTON_X1MASK) ? " [X2BUTTON]" : "",
1885 (mask & SDL_BUTTON_X2MASK) ? " [X2BUTTON]" : "");
1886 }
1887 break;
1888 case SDLK_0:
1889 if (withControl) {
1890 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1891 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Test Message", "You're awesome!", window);
1892 }
1893 break;
1894 case SDLK_1:
1895 if (withControl) {
1896 FullscreenTo(0, event->key.windowID);
1897 }
1898 break;
1899 case SDLK_2:
1900 if (withControl) {
1901 FullscreenTo(1, event->key.windowID);
1902 }
1903 break;
1904 case SDLK_ESCAPE:
1905 *done = 1;
1906 break;
1907 case SDLK_SPACE:
1908 {
1909 char message[256];
1910 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1911
1912 SDL_snprintf(message, sizeof(message), "(%" SDL_PRIs32 ", %" SDL_PRIs32 "), rel (%" SDL_PRIs32 ", %" SDL_PRIs32 ")\n",
1913 lastEvent.x, lastEvent.y, lastEvent.xrel, lastEvent.yrel);
1914 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Last mouse position", message, window);
1915 break;
1916 }
1917 default:
1918 break;
1919 }
1920 break;
1921 }
1922 case SDL_QUIT:
1923 *done = 1;
1924 break;
1925 case SDL_MOUSEMOTION:
1926 lastEvent = event->motion;
1927 break;
1928
1929 case SDL_DROPFILE:
1930 case SDL_DROPTEXT:
1931 SDL_free(event->drop.file);
1932 break;
1933 }
1934}
1935
1936void
1937SDLTest_CommonQuit(SDLTest_CommonState * state)
1938{
1939 int i;
1940
1941 SDL_free(common_usage_video);
1942 SDL_free(common_usage_audio);
1943 SDL_free(common_usage_videoaudio);
1944 common_usage_video = NULL;
1945 common_usage_audio = NULL;
1946 common_usage_videoaudio = NULL;
1947
1948 SDL_free(state->windows);
1949 if (state->targets) {
1950 for (i = 0; i < state->num_windows; ++i) {
1951 if (state->targets[i]) {
1952 SDL_DestroyTexture(state->targets[i]);
1953 }
1954 }
1955 SDL_free(state->targets);
1956 }
1957 if (state->renderers) {
1958 for (i = 0; i < state->num_windows; ++i) {
1959 if (state->renderers[i]) {
1960 SDL_DestroyRenderer(state->renderers[i]);
1961 }
1962 }
1963 SDL_free(state->renderers);
1964 }
1965 if (state->flags & SDL_INIT_VIDEO) {
1966 SDL_VideoQuit();
1967 }
1968 if (state->flags & SDL_INIT_AUDIO) {
1969 SDL_AudioQuit();
1970 }
1971 SDL_free(state);
1972 SDL_Quit();
1973 SDLTest_LogAllocations();
1974}
1975
1976/* vi: set ts=4 sw=4 expandtab: */
1977