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