SDL

Форк
0
/
SDL_test_common.c 
2729 строк · 97.0 Кб
1
/*
2
  Simple DirectMedia Layer
3
  Copyright (C) 1997-2024 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
#include <SDL3/SDL_test.h>
24

25
#define SDL_MAIN_NOIMPL
26
#define SDL_MAIN_USE_CALLBACKS
27
#include <SDL3/SDL_main.h>
28

29
static const char *common_usage[] = {
30
    "[-h | --help]",
31
    "[--trackmem]",
32
    "[--randmem]",
33
    "[--log all|error|system|audio|video|render|input]",
34
};
35

36
static const char *video_usage[] = {
37
    "[--always-on-top]",
38
    "[--aspect min-max]",
39
    "[--auto-scale-content]",
40
    "[--center | --position X,Y]",
41
    "[--confine-cursor X,Y,W,H]",
42
    "[--depth N]",
43
    "[--display N]",
44
    "[--flash-on-focus-loss]",
45
    "[--fullscreen | --fullscreen-desktop | --windows N]",
46
    "[--geometry WxH]",
47
    "[--gldebug]",
48
    "[--grab]",
49
    "[--hidden]",
50
    "[--hide-cursor]",
51
    "[--high-pixel-density]",
52
    "[--icon icon.bmp]",
53
    "[--info all|video|modes|render|event|event_motion]",
54
    "[--input-focus]",
55
    "[--keyboard-grab]",
56
    "[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]",
57
    "[--logical-scale-quality nearest|linear|best]",
58
    "[--logical WxH]",
59
    "[--max-geometry WxH]",
60
    "[--maximize]",
61
    "[--metal-window | --opengl-window | --vulkan-window]",
62
    "[--min-geometry WxH]",
63
    "[--minimize]",
64
    "[--mouse-focus]",
65
    "[--noframe]",
66
    "[--refresh R]",
67
    "[--renderer driver]",
68
    "[--resizable]",
69
    "[--scale N]",
70
    "[--title title]",
71
    "[--transparent]",
72
    "[--usable-bounds]",
73
    "[--utility]",
74
    "[--video driver]",
75
    "[--gpu driver]",
76
    "[--vsync]"
77
};
78

79
/* !!! FIXME: Float32? Sint32? */
80
static const char *audio_usage[] = {
81
    "[--audio driver]", "[--rate N]", "[--format U8|S8|S16|S16LE|S16BE|S32|S32LE|S32BE|F32|F32LE|F32BE]",
82
    "[--channels N]"
83
};
84

85
static void SDL_snprintfcat(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
86
{
87
    size_t length = SDL_strlen(text);
88
    va_list ap;
89

90
    va_start(ap, fmt);
91
    text += length;
92
    maxlen -= length;
93
    (void)SDL_vsnprintf(text, maxlen, fmt, ap);
94
    va_end(ap);
95
}
96

97
SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, SDL_InitFlags flags)
98
{
99
    int i;
100
    SDLTest_CommonState *state;
101

102
    /* Do this first so we catch all allocations */
103
    for (i = 1; argv[i]; ++i) {
104
        if (SDL_strcasecmp(argv[i], "--trackmem") == 0) {
105
            SDLTest_TrackAllocations();
106
        } else if (SDL_strcasecmp(argv[i], "--randmem") == 0) {
107
            SDLTest_RandFillAllocations();
108
        }
109
    }
110

111
    state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state));
112
    if (!state) {
113
        return NULL;
114
    }
115

116
    /* Initialize some defaults */
117
    state->argv = argv;
118
    state->flags = flags;
119
    state->window_title = argv[0];
120
    state->window_flags = SDL_WINDOW_HIDDEN;
121
    state->window_x = SDL_WINDOWPOS_UNDEFINED;
122
    state->window_y = SDL_WINDOWPOS_UNDEFINED;
123
    state->window_w = DEFAULT_WINDOW_WIDTH;
124
    state->window_h = DEFAULT_WINDOW_HEIGHT;
125
    state->logical_presentation = SDL_LOGICAL_PRESENTATION_DISABLED;
126
    state->logical_scale_mode = SDL_SCALEMODE_LINEAR;
127
    state->num_windows = 1;
128
    state->audio_freq = 22050;
129
    state->audio_format = SDL_AUDIO_S16;
130
    state->audio_channels = 2;
131

132
    /* Set some very sane GL defaults */
133
    state->gl_red_size = 8;
134
    state->gl_green_size = 8;
135
    state->gl_blue_size = 8;
136
    state->gl_alpha_size = 8;
137
    state->gl_buffer_size = 0;
138
    state->gl_depth_size = 16;
139
    state->gl_stencil_size = 0;
140
    state->gl_double_buffer = 1;
141
    state->gl_accum_red_size = 0;
142
    state->gl_accum_green_size = 0;
143
    state->gl_accum_blue_size = 0;
144
    state->gl_accum_alpha_size = 0;
145
    state->gl_stereo = 0;
146
    state->gl_multisamplebuffers = 0;
147
    state->gl_multisamplesamples = 0;
148
    state->gl_retained_backing = 1;
149
    state->gl_accelerated = -1;
150
    state->gl_debug = 0;
151

152
    return state;
153
}
154

155
void SDLTest_CommonDestroyState(SDLTest_CommonState *state) {
156
    SDL_free(state);
157
    SDLTest_LogAllocations();
158
}
159

160
#define SEARCHARG(dim)                  \
161
    while (*(dim) && *(dim) != ',') {   \
162
        ++(dim);                        \
163
    }                                   \
164
    if (!*(dim)) {                      \
165
        return -1;                      \
166
    }                                   \
167
    *(dim)++ = '\0';
168

169
int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
170
{
171
    char **argv = state->argv;
172

173
    if ((SDL_strcasecmp(argv[index], "-h") == 0) || (SDL_strcasecmp(argv[index], "--help") == 0)) {
174
        /* Print the usage message */
175
        return -1;
176
    }
177
    if (SDL_strcasecmp(argv[index], "--trackmem") == 0) {
178
        /* Already handled in SDLTest_CommonCreateState() */
179
        return 1;
180
    }
181
    if (SDL_strcasecmp(argv[index], "--randmem") == 0) {
182
        /* Already handled in SDLTest_CommonCreateState() */
183
        return 1;
184
    }
185
    if (SDL_strcasecmp(argv[index], "--log") == 0) {
186
        ++index;
187
        if (!argv[index]) {
188
            return -1;
189
        }
190
        if (SDL_strcasecmp(argv[index], "all") == 0) {
191
            SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
192
            return 2;
193
        }
194
        if (SDL_strcasecmp(argv[index], "error") == 0) {
195
            SDL_SetLogPriority(SDL_LOG_CATEGORY_ERROR, SDL_LOG_PRIORITY_VERBOSE);
196
            return 2;
197
        }
198
        if (SDL_strcasecmp(argv[index], "system") == 0) {
199
            SDL_SetLogPriority(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE);
200
            return 2;
201
        }
202
        if (SDL_strcasecmp(argv[index], "audio") == 0) {
203
            SDL_SetLogPriority(SDL_LOG_CATEGORY_AUDIO, SDL_LOG_PRIORITY_VERBOSE);
204
            return 2;
205
        }
206
        if (SDL_strcasecmp(argv[index], "video") == 0) {
207
            SDL_SetLogPriority(SDL_LOG_CATEGORY_VIDEO, SDL_LOG_PRIORITY_VERBOSE);
208
            return 2;
209
        }
210
        if (SDL_strcasecmp(argv[index], "render") == 0) {
211
            SDL_SetLogPriority(SDL_LOG_CATEGORY_RENDER, SDL_LOG_PRIORITY_VERBOSE);
212
            return 2;
213
        }
214
        if (SDL_strcasecmp(argv[index], "input") == 0) {
215
            SDL_SetLogPriority(SDL_LOG_CATEGORY_INPUT, SDL_LOG_PRIORITY_VERBOSE);
216
            return 2;
217
        }
218
        return -1;
219
    }
220
    if (state->flags & SDL_INIT_VIDEO) {
221
        if (SDL_strcasecmp(argv[index], "--video") == 0) {
222
            ++index;
223
            if (!argv[index]) {
224
                return -1;
225
            }
226
            state->videodriver = argv[index];
227
            SDL_SetHint(SDL_HINT_VIDEO_DRIVER, state->videodriver);
228
            return 2;
229
        }
230
        if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
231
            ++index;
232
            if (!argv[index]) {
233
                return -1;
234
            }
235
            state->renderdriver = argv[index];
236
            SDL_SetHint(SDL_HINT_RENDER_DRIVER, state->renderdriver);
237
            return 2;
238
        }
239
        if (SDL_strcasecmp(argv[index], "--gldebug") == 0) {
240
            state->gl_debug = 1;
241
            return 1;
242
        }
243
        if (SDL_strcasecmp(argv[index], "--info") == 0) {
244
            ++index;
245
            if (!argv[index]) {
246
                return -1;
247
            }
248
            if (SDL_strcasecmp(argv[index], "all") == 0) {
249
                state->verbose |=
250
                        (VERBOSE_VIDEO | VERBOSE_MODES | VERBOSE_RENDER |
251
                         VERBOSE_EVENT);
252
                return 2;
253
            }
254
            if (SDL_strcasecmp(argv[index], "video") == 0) {
255
                state->verbose |= VERBOSE_VIDEO;
256
                return 2;
257
            }
258
            if (SDL_strcasecmp(argv[index], "modes") == 0) {
259
                state->verbose |= VERBOSE_MODES;
260
                return 2;
261
            }
262
            if (SDL_strcasecmp(argv[index], "render") == 0) {
263
                state->verbose |= VERBOSE_RENDER;
264
                return 2;
265
            }
266
            if (SDL_strcasecmp(argv[index], "event") == 0) {
267
                state->verbose |= VERBOSE_EVENT;
268
                return 2;
269
            }
270
            if (SDL_strcasecmp(argv[index], "event_motion") == 0) {
271
                state->verbose |= (VERBOSE_EVENT | VERBOSE_MOTION);
272
                return 2;
273
            }
274
            return -1;
275
        }
276
        if (SDL_strcasecmp(argv[index], "--display") == 0) {
277
            ++index;
278
            if (!argv[index]) {
279
                return -1;
280
            }
281
            state->display_index = SDL_atoi(argv[index]);
282
            return 2;
283
        }
284
        if (SDL_strcasecmp(argv[index], "--metal-window") == 0) {
285
            state->window_flags |= SDL_WINDOW_METAL;
286
            return 1;
287
        }
288
        if (SDL_strcasecmp(argv[index], "--opengl-window") == 0) {
289
            state->window_flags |= SDL_WINDOW_OPENGL;
290
            return 1;
291
        }
292
        if (SDL_strcasecmp(argv[index], "--vulkan-window") == 0) {
293
            state->window_flags |= SDL_WINDOW_VULKAN;
294
            return 1;
295
        }
296
        if (SDL_strcasecmp(argv[index], "--fullscreen") == 0) {
297
            state->window_flags |= SDL_WINDOW_FULLSCREEN;
298
            state->fullscreen_exclusive = SDL_TRUE;
299
            state->num_windows = 1;
300
            return 1;
301
        }
302
        if (SDL_strcasecmp(argv[index], "--fullscreen-desktop") == 0) {
303
            state->window_flags |= SDL_WINDOW_FULLSCREEN;
304
            state->fullscreen_exclusive = SDL_FALSE;
305
            state->num_windows = 1;
306
            return 1;
307
        }
308
        if (SDL_strcasecmp(argv[index], "--windows") == 0) {
309
            ++index;
310
            if (!argv[index] || !SDL_isdigit((unsigned char) *argv[index])) {
311
                return -1;
312
            }
313
            if (!(state->window_flags & SDL_WINDOW_FULLSCREEN)) {
314
                state->num_windows = SDL_atoi(argv[index]);
315
            }
316
            return 2;
317
        }
318
        if (SDL_strcasecmp(argv[index], "--title") == 0) {
319
            ++index;
320
            if (!argv[index]) {
321
                return -1;
322
            }
323
            state->window_title = argv[index];
324
            return 2;
325
        }
326
        if (SDL_strcasecmp(argv[index], "--icon") == 0) {
327
            ++index;
328
            if (!argv[index]) {
329
                return -1;
330
            }
331
            state->window_icon = argv[index];
332
            return 2;
333
        }
334
        if (SDL_strcasecmp(argv[index], "--center") == 0) {
335
            state->window_x = SDL_WINDOWPOS_CENTERED;
336
            state->window_y = SDL_WINDOWPOS_CENTERED;
337
            return 1;
338
        }
339
        if (SDL_strcasecmp(argv[index], "--position") == 0) {
340
            char *x, *y;
341
            ++index;
342
            if (!argv[index]) {
343
                return -1;
344
            }
345
            x = argv[index];
346
            y = argv[index];
347
            while (*y && *y != ',') {
348
                ++y;
349
            }
350
            if (!*y) {
351
                return -1;
352
            }
353
            *y++ = '\0';
354
            state->window_x = SDL_atoi(x);
355
            state->window_y = SDL_atoi(y);
356
            return 2;
357
        }
358
        if (SDL_strcasecmp(argv[index], "--confine-cursor") == 0) {
359
            char *x, *y, *w, *h;
360
            ++index;
361
            if (!argv[index]) {
362
                return -1;
363
            }
364
            x = argv[index];
365
            y = argv[index];
366
            SEARCHARG(y)
367
            w = y;
368
            SEARCHARG(w)
369
            h = w;
370
            SEARCHARG(h)
371
            state->confine.x = SDL_atoi(x);
372
            state->confine.y = SDL_atoi(y);
373
            state->confine.w = SDL_atoi(w);
374
            state->confine.h = SDL_atoi(h);
375
            return 2;
376
        }
377
        if (SDL_strcasecmp(argv[index], "--usable-bounds") == 0) {
378
            state->fill_usable_bounds = SDL_TRUE;
379
            return 1;
380
        }
381
        if (SDL_strcasecmp(argv[index], "--geometry") == 0) {
382
            char *w, *h;
383
            ++index;
384
            if (!argv[index]) {
385
                return -1;
386
            }
387
            w = argv[index];
388
            h = argv[index];
389
            while (*h && *h != 'x') {
390
                ++h;
391
            }
392
            if (!*h) {
393
                return -1;
394
            }
395
            *h++ = '\0';
396
            state->window_w = SDL_atoi(w);
397
            state->window_h = SDL_atoi(h);
398
            return 2;
399
        }
400
        if (SDL_strcasecmp(argv[index], "--min-geometry") == 0) {
401
            char *w, *h;
402
            ++index;
403
            if (!argv[index]) {
404
                return -1;
405
            }
406
            w = argv[index];
407
            h = argv[index];
408
            while (*h && *h != 'x') {
409
                ++h;
410
            }
411
            if (!*h) {
412
                return -1;
413
            }
414
            *h++ = '\0';
415
            state->window_minW = SDL_atoi(w);
416
            state->window_minH = SDL_atoi(h);
417
            return 2;
418
        }
419
        if (SDL_strcasecmp(argv[index], "--max-geometry") == 0) {
420
            char *w, *h;
421
            ++index;
422
            if (!argv[index]) {
423
                return -1;
424
            }
425
            w = argv[index];
426
            h = argv[index];
427
            while (*h && *h != 'x') {
428
                ++h;
429
            }
430
            if (!*h) {
431
                return -1;
432
            }
433
            *h++ = '\0';
434
            state->window_maxW = SDL_atoi(w);
435
            state->window_maxH = SDL_atoi(h);
436
            return 2;
437
        }
438
        if (SDL_strcasecmp(argv[index], "--aspect") == 0) {
439
            char *min_aspect, *max_aspect;
440
            ++index;
441
            if (!argv[index]) {
442
                return -1;
443
            }
444
            min_aspect = argv[index];
445
            max_aspect = argv[index];
446
            while (*max_aspect && *max_aspect != '-') {
447
                ++max_aspect;
448
            }
449
            if (*max_aspect) {
450
                *max_aspect++ = '\0';
451
            } else {
452
                max_aspect = min_aspect;
453
            }
454
            state->window_min_aspect = (float)SDL_atof(min_aspect);
455
            state->window_max_aspect = (float)SDL_atof(max_aspect);
456
            return 2;
457
        }
458
        if (SDL_strcasecmp(argv[index], "--logical") == 0) {
459
            char *w, *h;
460
            ++index;
461
            if (!argv[index]) {
462
                return -1;
463
            }
464
            w = argv[index];
465
            h = argv[index];
466
            while (*h && *h != 'x') {
467
                ++h;
468
            }
469
            if (!*h) {
470
                return -1;
471
            }
472
            *h++ = '\0';
473
            state->logical_w = SDL_atoi(w);
474
            state->logical_h = SDL_atoi(h);
475
            return 2;
476
        }
477
        if (SDL_strcasecmp(argv[index], "--high-pixel-density") == 0) {
478
            state->window_flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
479
            return 1;
480
        }
481
        if (SDL_strcasecmp(argv[index], "--auto-scale-content") == 0) {
482
            state->auto_scale_content = SDL_TRUE;
483

484
            if (state->logical_presentation == SDL_LOGICAL_PRESENTATION_DISABLED) {
485
                state->logical_presentation = SDL_LOGICAL_PRESENTATION_STRETCH;
486
            }
487
            return 1;
488
        }
489
        if (SDL_strcasecmp(argv[index], "--logical-presentation") == 0) {
490
            ++index;
491
            if (!argv[index]) {
492
                return -1;
493
            }
494
            if (SDL_strcasecmp(argv[index], "disabled") == 0) {
495
                state->logical_presentation = SDL_LOGICAL_PRESENTATION_DISABLED;
496
                return 2;
497
            }
498
            if (SDL_strcasecmp(argv[index], "stretch") == 0) {
499
                state->logical_presentation = SDL_LOGICAL_PRESENTATION_STRETCH;
500
                return 2;
501
            }
502
            if (SDL_strcasecmp(argv[index], "letterbox") == 0) {
503
                state->logical_presentation = SDL_LOGICAL_PRESENTATION_LETTERBOX;
504
                return 2;
505
            }
506
            if (SDL_strcasecmp(argv[index], "overscan") == 0) {
507
                state->logical_presentation = SDL_LOGICAL_PRESENTATION_OVERSCAN;
508
                return 2;
509
            }
510
            if (SDL_strcasecmp(argv[index], "integer_scale") == 0) {
511
                state->logical_presentation = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE;
512
                return 2;
513
            }
514
            return -1;
515
        }
516
        if (SDL_strcasecmp(argv[index], "--logical-scale-quality") == 0) {
517
            ++index;
518
            if (!argv[index]) {
519
                return -1;
520
            }
521
            if (SDL_strcasecmp(argv[index], "nearest") == 0) {
522
                state->logical_scale_mode = SDL_SCALEMODE_NEAREST;
523
                return 2;
524
            }
525
            if (SDL_strcasecmp(argv[index], "linear") == 0) {
526
                state->logical_scale_mode = SDL_SCALEMODE_LINEAR;
527
                return 2;
528
            }
529
            return -1;
530
        }
531
        if (SDL_strcasecmp(argv[index], "--scale") == 0) {
532
            ++index;
533
            if (!argv[index]) {
534
                return -1;
535
            }
536
            state->scale = (float) SDL_atof(argv[index]);
537
            return 2;
538
        }
539
        if (SDL_strcasecmp(argv[index], "--depth") == 0) {
540
            ++index;
541
            if (!argv[index]) {
542
                return -1;
543
            }
544
            state->depth = SDL_atoi(argv[index]);
545
            return 2;
546
        }
547
        if (SDL_strcasecmp(argv[index], "--refresh") == 0) {
548
            ++index;
549
            if (!argv[index]) {
550
                return -1;
551
            }
552
            state->refresh_rate = (float) SDL_atof(argv[index]);
553
            return 2;
554
        }
555
        if (SDL_strcasecmp(argv[index], "--vsync") == 0) {
556
            state->render_vsync = 1;
557
            return 1;
558
        }
559
        if (SDL_strcasecmp(argv[index], "--noframe") == 0) {
560
            state->window_flags |= SDL_WINDOW_BORDERLESS;
561
            return 1;
562
        }
563
        if (SDL_strcasecmp(argv[index], "--resizable") == 0) {
564
            state->window_flags |= SDL_WINDOW_RESIZABLE;
565
            return 1;
566
        }
567
        if (SDL_strcasecmp(argv[index], "--transparent") == 0) {
568
            state->window_flags |= SDL_WINDOW_TRANSPARENT;
569
            return 1;
570
        }
571
        if (SDL_strcasecmp(argv[index], "--always-on-top") == 0) {
572
            state->window_flags |= SDL_WINDOW_ALWAYS_ON_TOP;
573
            return 1;
574
        }
575
        if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
576
            state->window_flags |= SDL_WINDOW_MINIMIZED;
577
            return 1;
578
        }
579
        if (SDL_strcasecmp(argv[index], "--maximize") == 0) {
580
            state->window_flags |= SDL_WINDOW_MAXIMIZED;
581
            return 1;
582
        }
583
        if (SDL_strcasecmp(argv[index], "--hidden") == 0) {
584
            state->window_flags |= SDL_WINDOW_HIDDEN;
585
            return 1;
586
        }
587
        if (SDL_strcasecmp(argv[index], "--input-focus") == 0) {
588
            state->window_flags |= SDL_WINDOW_INPUT_FOCUS;
589
            return 1;
590
        }
591
        if (SDL_strcasecmp(argv[index], "--mouse-focus") == 0) {
592
            state->window_flags |= SDL_WINDOW_MOUSE_FOCUS;
593
            return 1;
594
        }
595
        if (SDL_strcasecmp(argv[index], "--flash-on-focus-loss") == 0) {
596
            state->flash_on_focus_loss = SDL_TRUE;
597
            return 1;
598
        }
599
        if (SDL_strcasecmp(argv[index], "--grab") == 0) {
600
            state->window_flags |= SDL_WINDOW_MOUSE_GRABBED;
601
            return 1;
602
        }
603
        if (SDL_strcasecmp(argv[index], "--keyboard-grab") == 0) {
604
            state->window_flags |= SDL_WINDOW_KEYBOARD_GRABBED;
605
            return 1;
606
        }
607
        if (SDL_strcasecmp(argv[index], "--utility") == 0) {
608
            state->window_flags |= SDL_WINDOW_UTILITY;
609
            return 1;
610
        }
611
        if (SDL_strcasecmp(argv[index], "--hide-cursor") == 0) {
612
            state->hide_cursor = SDL_TRUE;
613
            return 1;
614
        }
615
        if (SDL_strcasecmp(argv[index], "--gpu") == 0) {
616
            ++index;
617
            if (!argv[index]) {
618
                return -1;
619
            }
620
            state->gpudriver = argv[index];
621
            SDL_SetHint(SDL_HINT_GPU_DRIVER, state->gpudriver);
622
            return 2;
623
        }
624
    } else {
625
        if (SDL_strcasecmp(argv[index], "--info") == 0) {
626
            ++index;
627
            if (!argv[index]) {
628
                return -1;
629
            }
630
            if (SDL_strcasecmp(argv[index], "all") == 0) {
631
                state->verbose |= VERBOSE_EVENT;
632
                return 2;
633
            }
634
            if (SDL_strcasecmp(argv[index], "event") == 0) {
635
                state->verbose |= VERBOSE_EVENT;
636
                return 2;
637
            }
638
            return -1;
639
        }
640
    }
641

642
    if (state->flags & SDL_INIT_AUDIO) {
643
        if (SDL_strcasecmp(argv[index], "--audio") == 0) {
644
            ++index;
645
            if (!argv[index]) {
646
                return -1;
647
            }
648
            state->audiodriver = argv[index];
649
            SDL_SetHint(SDL_HINT_AUDIO_DRIVER, state->audiodriver);
650
            return 2;
651
        }
652
        if (SDL_strcasecmp(argv[index], "--rate") == 0) {
653
            ++index;
654
            if (!argv[index]) {
655
                return -1;
656
            }
657
            state->audio_freq = SDL_atoi(argv[index]);
658
            return 2;
659
        }
660
        if (SDL_strcasecmp(argv[index], "--format") == 0) {
661
            ++index;
662
            if (!argv[index]) {
663
                return -1;
664
            }
665
            if (SDL_strcasecmp(argv[index], "U8") == 0) {
666
                state->audio_format = SDL_AUDIO_U8;
667
                return 2;
668
            }
669
            if (SDL_strcasecmp(argv[index], "S8") == 0) {
670
                state->audio_format = SDL_AUDIO_S8;
671
                return 2;
672
            }
673
            if (SDL_strcasecmp(argv[index], "S16") == 0) {
674
                state->audio_format = SDL_AUDIO_S16;
675
                return 2;
676
            }
677
            if (SDL_strcasecmp(argv[index], "S16LE") == 0) {
678
                state->audio_format = SDL_AUDIO_S16LE;
679
                return 2;
680
            }
681
            if (SDL_strcasecmp(argv[index], "S16BE") == 0) {
682
                state->audio_format = SDL_AUDIO_S16BE;
683
                return 2;
684
            }
685
            if (SDL_strcasecmp(argv[index], "S32") == 0) {
686
                state->audio_format = SDL_AUDIO_S32;
687
                return 2;
688
            }
689
            if (SDL_strcasecmp(argv[index], "S32LE") == 0) {
690
                state->audio_format = SDL_AUDIO_S32LE;
691
                return 2;
692
            }
693
            if (SDL_strcasecmp(argv[index], "S32BE") == 0) {
694
                state->audio_format = SDL_AUDIO_S32BE;
695
                return 2;
696
            }
697
            if (SDL_strcasecmp(argv[index], "F32") == 0) {
698
                state->audio_format = SDL_AUDIO_F32;
699
                return 2;
700
            }
701
            if (SDL_strcasecmp(argv[index], "F32LE") == 0) {
702
                state->audio_format = SDL_AUDIO_F32LE;
703
                return 2;
704
            }
705
            if (SDL_strcasecmp(argv[index], "F32BE") == 0) {
706
                state->audio_format = SDL_AUDIO_F32BE;
707
                return 2;
708
            }
709
            return -1;
710
        }
711
        if (SDL_strcasecmp(argv[index], "--channels") == 0) {
712
            ++index;
713
            if (!argv[index]) {
714
                return -1;
715
            }
716
            state->audio_channels = (Uint8) SDL_atoi(argv[index]);
717
            return 2;
718
        }
719
    }
720
    if (SDL_strcmp(argv[index], "-NSDocumentRevisionsDebugMode") == 0) {
721
        /* Debug flag sent by Xcode */
722
        return 2;
723
    }
724
    return 0;
725
}
726

727
void SDLTest_CommonLogUsage(SDLTest_CommonState *state, const char *argv0, const char **options)
728
{
729
    int i;
730

731
    SDL_Log("USAGE: %s", argv0);
732

733
    for (i = 0; i < SDL_arraysize(common_usage); i++) {
734
        SDL_Log("    %s", common_usage[i]);
735
    }
736

737
    if (state->flags & SDL_INIT_VIDEO) {
738
        for (i = 0; i < SDL_arraysize(video_usage); i++) {
739
            SDL_Log("    %s", video_usage[i]);
740
        }
741
    }
742

743
    if (state->flags & SDL_INIT_AUDIO) {
744
        for (i = 0; i < SDL_arraysize(audio_usage); i++) {
745
            SDL_Log("    %s", audio_usage[i]);
746
        }
747
    }
748

749
    if (options) {
750
        for (i = 0; options[i] != NULL; i++) {
751
            SDL_Log("    %s", options[i]);
752
        }
753
    }
754
}
755

756
static char *common_usage_video = NULL;
757
static char *common_usage_audio = NULL;
758
static char *common_usage_videoaudio = NULL;
759

760
SDL_bool SDLTest_CommonDefaultArgs(SDLTest_CommonState *state, const int argc, char **argv)
761
{
762
    int i = 1;
763
    while (i < argc) {
764
        const int consumed = SDLTest_CommonArg(state, i);
765
        if (consumed <= 0) {
766
            SDLTest_CommonLogUsage(state, argv[0], NULL);
767
            return SDL_FALSE;
768
        }
769
        i += consumed;
770
    }
771
    return SDL_TRUE;
772
}
773

774
static void SDLTest_PrintDisplayOrientation(char *text, size_t maxlen, SDL_DisplayOrientation orientation)
775
{
776
    switch (orientation) {
777
    case SDL_ORIENTATION_UNKNOWN:
778
        SDL_snprintfcat(text, maxlen, "UNKNOWN");
779
        break;
780
    case SDL_ORIENTATION_LANDSCAPE:
781
        SDL_snprintfcat(text, maxlen, "LANDSCAPE");
782
        break;
783
    case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
784
        SDL_snprintfcat(text, maxlen, "LANDSCAPE_FLIPPED");
785
        break;
786
    case SDL_ORIENTATION_PORTRAIT:
787
        SDL_snprintfcat(text, maxlen, "PORTRAIT");
788
        break;
789
    case SDL_ORIENTATION_PORTRAIT_FLIPPED:
790
        SDL_snprintfcat(text, maxlen, "PORTRAIT_FLIPPED");
791
        break;
792
    default:
793
        SDL_snprintfcat(text, maxlen, "0x%8.8x", orientation);
794
        break;
795
    }
796
}
797

798
static void SDLTest_PrintWindowFlag(char *text, size_t maxlen, SDL_WindowFlags flag)
799
{
800
    switch (flag) {
801
    case SDL_WINDOW_FULLSCREEN:
802
        SDL_snprintfcat(text, maxlen, "FULLSCREEN");
803
        break;
804
    case SDL_WINDOW_OPENGL:
805
        SDL_snprintfcat(text, maxlen, "OPENGL");
806
        break;
807
    case SDL_WINDOW_HIDDEN:
808
        SDL_snprintfcat(text, maxlen, "HIDDEN");
809
        break;
810
    case SDL_WINDOW_BORDERLESS:
811
        SDL_snprintfcat(text, maxlen, "BORDERLESS");
812
        break;
813
    case SDL_WINDOW_RESIZABLE:
814
        SDL_snprintfcat(text, maxlen, "RESIZABLE");
815
        break;
816
    case SDL_WINDOW_MINIMIZED:
817
        SDL_snprintfcat(text, maxlen, "MINIMIZED");
818
        break;
819
    case SDL_WINDOW_MAXIMIZED:
820
        SDL_snprintfcat(text, maxlen, "MAXIMIZED");
821
        break;
822
    case SDL_WINDOW_MOUSE_GRABBED:
823
        SDL_snprintfcat(text, maxlen, "MOUSE_GRABBED");
824
        break;
825
    case SDL_WINDOW_INPUT_FOCUS:
826
        SDL_snprintfcat(text, maxlen, "INPUT_FOCUS");
827
        break;
828
    case SDL_WINDOW_MOUSE_FOCUS:
829
        SDL_snprintfcat(text, maxlen, "MOUSE_FOCUS");
830
        break;
831
    case SDL_WINDOW_EXTERNAL:
832
        SDL_snprintfcat(text, maxlen, "EXTERNAL");
833
        break;
834
    case SDL_WINDOW_HIGH_PIXEL_DENSITY:
835
        SDL_snprintfcat(text, maxlen, "HIGH_PIXEL_DENSITY");
836
        break;
837
    case SDL_WINDOW_MOUSE_CAPTURE:
838
        SDL_snprintfcat(text, maxlen, "MOUSE_CAPTURE");
839
        break;
840
    case SDL_WINDOW_ALWAYS_ON_TOP:
841
        SDL_snprintfcat(text, maxlen, "ALWAYS_ON_TOP");
842
        break;
843
    case SDL_WINDOW_UTILITY:
844
        SDL_snprintfcat(text, maxlen, "UTILITY");
845
        break;
846
    case SDL_WINDOW_TOOLTIP:
847
        SDL_snprintfcat(text, maxlen, "TOOLTIP");
848
        break;
849
    case SDL_WINDOW_POPUP_MENU:
850
        SDL_snprintfcat(text, maxlen, "POPUP_MENU");
851
        break;
852
    case SDL_WINDOW_KEYBOARD_GRABBED:
853
        SDL_snprintfcat(text, maxlen, "KEYBOARD_GRABBED");
854
        break;
855
    case SDL_WINDOW_VULKAN:
856
        SDL_snprintfcat(text, maxlen, "VULKAN");
857
        break;
858
    case SDL_WINDOW_METAL:
859
        SDL_snprintfcat(text, maxlen, "METAL");
860
        break;
861
    case SDL_WINDOW_TRANSPARENT:
862
        SDL_snprintfcat(text, maxlen, "TRANSPARENT");
863
        break;
864
    default:
865
        SDL_snprintfcat(text, maxlen, "0x%16.16" SDL_PRIx64, flag);
866
        break;
867
    }
868
}
869

870
static void SDLTest_PrintWindowFlags(char *text, size_t maxlen, SDL_WindowFlags flags)
871
{
872
    const SDL_WindowFlags window_flags[] = {
873
        SDL_WINDOW_FULLSCREEN,
874
        SDL_WINDOW_OPENGL,
875
        SDL_WINDOW_HIDDEN,
876
        SDL_WINDOW_BORDERLESS,
877
        SDL_WINDOW_RESIZABLE,
878
        SDL_WINDOW_MINIMIZED,
879
        SDL_WINDOW_MAXIMIZED,
880
        SDL_WINDOW_MOUSE_GRABBED,
881
        SDL_WINDOW_INPUT_FOCUS,
882
        SDL_WINDOW_MOUSE_FOCUS,
883
        SDL_WINDOW_EXTERNAL,
884
        SDL_WINDOW_HIGH_PIXEL_DENSITY,
885
        SDL_WINDOW_MOUSE_CAPTURE,
886
        SDL_WINDOW_ALWAYS_ON_TOP,
887
        SDL_WINDOW_UTILITY,
888
        SDL_WINDOW_TOOLTIP,
889
        SDL_WINDOW_POPUP_MENU,
890
        SDL_WINDOW_KEYBOARD_GRABBED,
891
        SDL_WINDOW_VULKAN,
892
        SDL_WINDOW_METAL,
893
        SDL_WINDOW_TRANSPARENT
894
    };
895

896
    int i;
897
    int count = 0;
898
    for (i = 0; i < (sizeof(window_flags) / sizeof(window_flags[0])); ++i) {
899
        const SDL_WindowFlags flag = window_flags[i];
900
        if ((flags & flag) == flag) {
901
            if (count > 0) {
902
                SDL_snprintfcat(text, maxlen, " | ");
903
            }
904
            SDLTest_PrintWindowFlag(text, maxlen, flag);
905
            ++count;
906
        }
907
    }
908
}
909

910
static void SDLTest_PrintModStateFlag(char *text, size_t maxlen, SDL_Keymod flag)
911
{
912
    switch (flag) {
913
    case SDL_KMOD_LSHIFT:
914
        SDL_snprintfcat(text, maxlen, "LSHIFT");
915
        break;
916
    case SDL_KMOD_RSHIFT:
917
        SDL_snprintfcat(text, maxlen, "RSHIFT");
918
        break;
919
    case SDL_KMOD_LCTRL:
920
        SDL_snprintfcat(text, maxlen, "LCTRL");
921
        break;
922
    case SDL_KMOD_RCTRL:
923
        SDL_snprintfcat(text, maxlen, "RCTRL");
924
        break;
925
    case SDL_KMOD_LALT:
926
        SDL_snprintfcat(text, maxlen, "LALT");
927
        break;
928
    case SDL_KMOD_RALT:
929
        SDL_snprintfcat(text, maxlen, "RALT");
930
        break;
931
    case SDL_KMOD_LGUI:
932
        SDL_snprintfcat(text, maxlen, "LGUI");
933
        break;
934
    case SDL_KMOD_RGUI:
935
        SDL_snprintfcat(text, maxlen, "RGUI");
936
        break;
937
    case SDL_KMOD_NUM:
938
        SDL_snprintfcat(text, maxlen, "NUM");
939
        break;
940
    case SDL_KMOD_CAPS:
941
        SDL_snprintfcat(text, maxlen, "CAPS");
942
        break;
943
    case SDL_KMOD_MODE:
944
        SDL_snprintfcat(text, maxlen, "MODE");
945
        break;
946
    case SDL_KMOD_SCROLL:
947
        SDL_snprintfcat(text, maxlen, "SCROLL");
948
        break;
949
    default:
950
        SDL_snprintfcat(text, maxlen, "0x%8.8x", (unsigned int) flag);
951
        break;
952
    }
953
}
954

955
static void SDLTest_PrintModState(char *text, size_t maxlen, SDL_Keymod keymod)
956
{
957
    const SDL_Keymod kmod_flags[] = {
958
        SDL_KMOD_LSHIFT,
959
        SDL_KMOD_RSHIFT,
960
        SDL_KMOD_LCTRL,
961
        SDL_KMOD_RCTRL,
962
        SDL_KMOD_LALT,
963
        SDL_KMOD_RALT,
964
        SDL_KMOD_LGUI,
965
        SDL_KMOD_RGUI,
966
        SDL_KMOD_NUM,
967
        SDL_KMOD_CAPS,
968
        SDL_KMOD_MODE,
969
        SDL_KMOD_SCROLL
970
    };
971

972
    int i;
973
    int count = 0;
974
    for (i = 0; i < SDL_arraysize(kmod_flags); ++i) {
975
        const SDL_Keymod flag = kmod_flags[i];
976
        if ((keymod & flag) == flag) {
977
            if (count > 0) {
978
                SDL_snprintfcat(text, maxlen, " | ");
979
            }
980
            SDLTest_PrintModStateFlag(text, maxlen, flag);
981
            ++count;
982
        }
983
    }
984
}
985

986
static void SDLTest_PrintButtonMask(char *text, size_t maxlen, SDL_MouseButtonFlags flags)
987
{
988
    int i;
989
    int count = 0;
990
    for (i = 1; i <= 32; ++i) {
991
        const Uint32 flag = SDL_BUTTON(i);
992
        if ((flags & flag) == flag) {
993
            if (count > 0) {
994
                SDL_snprintfcat(text, maxlen, " | ");
995
            }
996
            SDL_snprintfcat(text, maxlen, "SDL_BUTTON(%d)", i);
997
            ++count;
998
        }
999
    }
1000
}
1001

1002
static void SDLTest_PrintPixelFormat(char *text, size_t maxlen, Uint32 format)
1003
{
1004
    const char *name = SDL_GetPixelFormatName(format);
1005
    if (name) {
1006
        if (SDL_strncmp(name, "SDL_PIXELFORMAT_", 16) == 0) {
1007
            name += 16;
1008
        }
1009
        SDL_snprintfcat(text, maxlen, name);
1010
    } else {
1011
        SDL_snprintfcat(text, maxlen, "0x%8.8x", format);
1012
    }
1013
}
1014

1015
static void SDLTest_PrintLogicalPresentation(char *text, size_t maxlen, SDL_RendererLogicalPresentation logical_presentation)
1016
{
1017
    switch (logical_presentation) {
1018
    case SDL_LOGICAL_PRESENTATION_DISABLED:
1019
        SDL_snprintfcat(text, maxlen, "DISABLED");
1020
        break;
1021
    case SDL_LOGICAL_PRESENTATION_STRETCH:
1022
        SDL_snprintfcat(text, maxlen, "STRETCH");
1023
        break;
1024
    case SDL_LOGICAL_PRESENTATION_LETTERBOX:
1025
        SDL_snprintfcat(text, maxlen, "LETTERBOX");
1026
        break;
1027
    case SDL_LOGICAL_PRESENTATION_OVERSCAN:
1028
        SDL_snprintfcat(text, maxlen, "OVERSCAN");
1029
        break;
1030
    case SDL_LOGICAL_PRESENTATION_INTEGER_SCALE:
1031
        SDL_snprintfcat(text, maxlen, "INTEGER_SCALE");
1032
        break;
1033
    default:
1034
        SDL_snprintfcat(text, maxlen, "0x%8.8x", logical_presentation);
1035
        break;
1036
    }
1037
}
1038

1039
static void SDLTest_PrintScaleMode(char *text, size_t maxlen, SDL_ScaleMode scale_mode)
1040
{
1041
    switch (scale_mode) {
1042
    case SDL_SCALEMODE_NEAREST:
1043
        SDL_snprintfcat(text, maxlen, "NEAREST");
1044
        break;
1045
    case SDL_SCALEMODE_LINEAR:
1046
        SDL_snprintfcat(text, maxlen, "LINEAR");
1047
        break;
1048
    default:
1049
        SDL_snprintfcat(text, maxlen, "0x%8.8x", scale_mode);
1050
        break;
1051
    }
1052
}
1053

1054
static void SDLTest_PrintRenderer(SDL_Renderer *renderer)
1055
{
1056
    const char *name;
1057
    int i;
1058
    char text[1024];
1059
    int max_texture_size;
1060
    const SDL_PixelFormat *texture_formats;
1061

1062
    name = SDL_GetRendererName(renderer);
1063

1064
    SDL_Log("  Renderer %s:\n", name);
1065
    SDL_Log("    VSync: %d\n", (int)SDL_GetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_VSYNC_NUMBER, 0));
1066

1067
    texture_formats = (const SDL_PixelFormat *)SDL_GetPointerProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_TEXTURE_FORMATS_POINTER, NULL);
1068
    if (texture_formats) {
1069
        (void)SDL_snprintf(text, sizeof(text), "    Texture formats: ");
1070
        for (i = 0; texture_formats[i]; ++i) {
1071
            if (i > 0) {
1072
                SDL_snprintfcat(text, sizeof(text), ", ");
1073
            }
1074
            SDLTest_PrintPixelFormat(text, sizeof(text), texture_formats[i]);
1075
        }
1076
        SDL_Log("%s\n", text);
1077
    }
1078

1079
    max_texture_size = (int)SDL_GetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 0);
1080
    if (max_texture_size) {
1081
        SDL_Log("    Max Texture Size: %dx%d\n", max_texture_size, max_texture_size);
1082
    }
1083
}
1084

1085
static SDL_Surface *SDLTest_LoadIcon(const char *file)
1086
{
1087
    SDL_Surface *icon;
1088

1089
    /* Load the icon surface */
1090
    icon = SDL_LoadBMP(file);
1091
    if (!icon) {
1092
        SDL_Log("Couldn't load %s: %s\n", file, SDL_GetError());
1093
        return NULL;
1094
    }
1095

1096
    if (icon->format == SDL_PIXELFORMAT_INDEX8) {
1097
        /* Set the colorkey */
1098
        SDL_SetSurfaceColorKey(icon, 1, *((Uint8 *)icon->pixels));
1099
    }
1100

1101
    return icon;
1102
}
1103

1104
static SDL_HitTestResult SDLCALL SDLTest_ExampleHitTestCallback(SDL_Window *win, const SDL_Point *area, void *data)
1105
{
1106
    int w, h;
1107
    const int RESIZE_BORDER = 8;
1108
    const int DRAGGABLE_TITLE = 32;
1109

1110
    /*SDL_Log("Hit test point %d,%d\n", area->x, area->y);*/
1111

1112
    SDL_GetWindowSize(win, &w, &h);
1113

1114
    if (area->x < RESIZE_BORDER) {
1115
        if (area->y < RESIZE_BORDER) {
1116
            SDL_Log("SDL_HITTEST_RESIZE_TOPLEFT\n");
1117
            return SDL_HITTEST_RESIZE_TOPLEFT;
1118
        } else if (area->y >= (h - RESIZE_BORDER)) {
1119
            SDL_Log("SDL_HITTEST_RESIZE_BOTTOMLEFT\n");
1120
            return SDL_HITTEST_RESIZE_BOTTOMLEFT;
1121
        } else {
1122
            SDL_Log("SDL_HITTEST_RESIZE_LEFT\n");
1123
            return SDL_HITTEST_RESIZE_LEFT;
1124
        }
1125
    } else if (area->x >= (w - RESIZE_BORDER)) {
1126
        if (area->y < RESIZE_BORDER) {
1127
            SDL_Log("SDL_HITTEST_RESIZE_TOPRIGHT\n");
1128
            return SDL_HITTEST_RESIZE_TOPRIGHT;
1129
        } else if (area->y >= (h - RESIZE_BORDER)) {
1130
            SDL_Log("SDL_HITTEST_RESIZE_BOTTOMRIGHT\n");
1131
            return SDL_HITTEST_RESIZE_BOTTOMRIGHT;
1132
        } else {
1133
            SDL_Log("SDL_HITTEST_RESIZE_RIGHT\n");
1134
            return SDL_HITTEST_RESIZE_RIGHT;
1135
        }
1136
    } else if (area->y >= (h - RESIZE_BORDER)) {
1137
        SDL_Log("SDL_HITTEST_RESIZE_BOTTOM\n");
1138
        return SDL_HITTEST_RESIZE_BOTTOM;
1139
    } else if (area->y < RESIZE_BORDER) {
1140
        SDL_Log("SDL_HITTEST_RESIZE_TOP\n");
1141
        return SDL_HITTEST_RESIZE_TOP;
1142
    } else if (area->y < DRAGGABLE_TITLE) {
1143
        SDL_Log("SDL_HITTEST_DRAGGABLE\n");
1144
        return SDL_HITTEST_DRAGGABLE;
1145
    }
1146
    return SDL_HITTEST_NORMAL;
1147
}
1148

1149
SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state)
1150
{
1151
    int i, j, m, n, w, h;
1152
    char text[1024];
1153

1154
    if (state->flags & SDL_INIT_VIDEO) {
1155
        if (state->verbose & VERBOSE_VIDEO) {
1156
            n = SDL_GetNumVideoDrivers();
1157
            if (n == 0) {
1158
                SDL_Log("No built-in video drivers\n");
1159
            } else {
1160
                (void)SDL_snprintf(text, sizeof(text), "Built-in video drivers:");
1161
                for (i = 0; i < n; ++i) {
1162
                    if (i > 0) {
1163
                        SDL_snprintfcat(text, sizeof(text), ",");
1164
                    }
1165
                    SDL_snprintfcat(text, sizeof(text), " %s", SDL_GetVideoDriver(i));
1166
                }
1167
                SDL_Log("%s\n", text);
1168
            }
1169
        }
1170
        if (!SDL_InitSubSystem(SDL_INIT_VIDEO)) {
1171
            SDL_Log("Couldn't initialize video driver: %s\n",
1172
                    SDL_GetError());
1173
            return SDL_FALSE;
1174
        }
1175
        if (state->verbose & VERBOSE_VIDEO) {
1176
            SDL_Log("Video driver: %s\n",
1177
                    SDL_GetCurrentVideoDriver());
1178
        }
1179

1180
        /* Upload GL settings */
1181
        SDL_GL_SetAttribute(SDL_GL_RED_SIZE, state->gl_red_size);
1182
        SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, state->gl_green_size);
1183
        SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, state->gl_blue_size);
1184
        SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, state->gl_alpha_size);
1185
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, state->gl_double_buffer);
1186
        SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, state->gl_buffer_size);
1187
        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, state->gl_depth_size);
1188
        SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, state->gl_stencil_size);
1189
        SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, state->gl_accum_red_size);
1190
        SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, state->gl_accum_green_size);
1191
        SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, state->gl_accum_blue_size);
1192
        SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, state->gl_accum_alpha_size);
1193
        SDL_GL_SetAttribute(SDL_GL_STEREO, state->gl_stereo);
1194
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, state->gl_multisamplebuffers);
1195
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, state->gl_multisamplesamples);
1196
        if (state->gl_accelerated >= 0) {
1197
            SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,
1198
                                state->gl_accelerated);
1199
        }
1200
        SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, state->gl_retained_backing);
1201
        if (state->gl_major_version) {
1202
            SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, state->gl_major_version);
1203
            SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, state->gl_minor_version);
1204
        }
1205
        if (state->gl_debug) {
1206
            SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
1207
        }
1208
        if (state->gl_profile_mask) {
1209
            SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, state->gl_profile_mask);
1210
        }
1211

1212
        if (state->verbose & VERBOSE_MODES) {
1213
            SDL_DisplayID *displays;
1214
            SDL_Rect bounds, usablebounds;
1215
            SDL_DisplayMode **modes;
1216
            const SDL_DisplayMode *mode;
1217
            int bpp;
1218
            Uint32 Rmask, Gmask, Bmask, Amask;
1219
#ifdef SDL_VIDEO_DRIVER_WINDOWS
1220
            int adapterIndex = 0;
1221
            int outputIndex = 0;
1222
#endif
1223
            displays = SDL_GetDisplays(&n);
1224
            SDL_Log("Number of displays: %d\n", n);
1225
            for (i = 0; i < n; ++i) {
1226
                SDL_DisplayID displayID = displays[i];
1227
                SDL_Log("Display %" SDL_PRIu32 ": %s\n", displayID, SDL_GetDisplayName(displayID));
1228

1229
                SDL_zero(bounds);
1230
                SDL_GetDisplayBounds(displayID, &bounds);
1231

1232
                SDL_zero(usablebounds);
1233
                SDL_GetDisplayUsableBounds(displayID, &usablebounds);
1234

1235
                SDL_Log("Bounds: %dx%d at %d,%d\n", bounds.w, bounds.h, bounds.x, bounds.y);
1236
                SDL_Log("Usable bounds: %dx%d at %d,%d\n", usablebounds.w, usablebounds.h, usablebounds.x, usablebounds.y);
1237

1238
                mode = SDL_GetDesktopDisplayMode(displayID);
1239
                SDL_GetMasksForPixelFormat(mode->format, &bpp, &Rmask, &Gmask,
1240
                                           &Bmask, &Amask);
1241
                SDL_Log("  Desktop mode: %dx%d@%gx %gHz, %d bits-per-pixel (%s)\n",
1242
                        mode->w, mode->h, mode->pixel_density, mode->refresh_rate, bpp,
1243
                        SDL_GetPixelFormatName(mode->format));
1244
                if (Rmask || Gmask || Bmask) {
1245
                    SDL_Log("      Red Mask   = 0x%.8" SDL_PRIx32 "\n", Rmask);
1246
                    SDL_Log("      Green Mask = 0x%.8" SDL_PRIx32 "\n", Gmask);
1247
                    SDL_Log("      Blue Mask  = 0x%.8" SDL_PRIx32 "\n", Bmask);
1248
                    if (Amask) {
1249
                        SDL_Log("      Alpha Mask = 0x%.8" SDL_PRIx32 "\n", Amask);
1250
                    }
1251
                }
1252

1253
                /* Print available fullscreen video modes */
1254
                modes = SDL_GetFullscreenDisplayModes(displayID, &m);
1255
                if (m == 0) {
1256
                    SDL_Log("No available fullscreen video modes\n");
1257
                } else {
1258
                    SDL_Log("  Fullscreen video modes:\n");
1259
                    for (j = 0; j < m; ++j) {
1260
                        mode = modes[j];
1261
                        SDL_GetMasksForPixelFormat(mode->format, &bpp, &Rmask,
1262
                                                   &Gmask, &Bmask, &Amask);
1263
                        SDL_Log("    Mode %d: %dx%d@%gx %gHz, %d bits-per-pixel (%s)\n",
1264
                                j, mode->w, mode->h, mode->pixel_density, mode->refresh_rate, bpp,
1265
                                SDL_GetPixelFormatName(mode->format));
1266
                        if (Rmask || Gmask || Bmask) {
1267
                            SDL_Log("        Red Mask   = 0x%.8" SDL_PRIx32 "\n",
1268
                                    Rmask);
1269
                            SDL_Log("        Green Mask = 0x%.8" SDL_PRIx32 "\n",
1270
                                    Gmask);
1271
                            SDL_Log("        Blue Mask  = 0x%.8" SDL_PRIx32 "\n",
1272
                                    Bmask);
1273
                            if (Amask) {
1274
                                SDL_Log("        Alpha Mask = 0x%.8" SDL_PRIx32 "\n", Amask);
1275
                            }
1276
                        }
1277
                    }
1278
                }
1279
                SDL_free(modes);
1280

1281
#if defined(SDL_VIDEO_DRIVER_WINDOWS) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
1282
                /* Print the D3D9 adapter index */
1283
                adapterIndex = SDL_GetDirect3D9AdapterIndex(displayID);
1284
                SDL_Log("D3D9 Adapter Index: %d", adapterIndex);
1285

1286
                /* Print the DXGI adapter and output indices */
1287
                SDL_GetDXGIOutputInfo(displayID, &adapterIndex, &outputIndex);
1288
                SDL_Log("DXGI Adapter Index: %d  Output Index: %d", adapterIndex, outputIndex);
1289
#endif
1290
            }
1291
            SDL_free(displays);
1292
        }
1293

1294
        if (state->verbose & VERBOSE_RENDER) {
1295
            n = SDL_GetNumRenderDrivers();
1296
            if (n == 0) {
1297
                SDL_Log("No built-in render drivers\n");
1298
            } else {
1299
                SDL_Log("Built-in render drivers:\n");
1300
                for (i = 0; i < n; ++i) {
1301
                    SDL_Log("  %s\n", SDL_GetRenderDriver(i));
1302
                }
1303
            }
1304
        }
1305

1306
        state->displayID = SDL_GetPrimaryDisplay();
1307
        if (state->display_index > 0) {
1308
            SDL_DisplayID *displays = SDL_GetDisplays(&n);
1309
            if (state->display_index < n) {
1310
                state->displayID = displays[state->display_index];
1311
            }
1312
            SDL_free(displays);
1313

1314
            if (SDL_WINDOWPOS_ISUNDEFINED(state->window_x)) {
1315
                state->window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->displayID);
1316
                state->window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->displayID);
1317
            } else if (SDL_WINDOWPOS_ISCENTERED(state->window_x)) {
1318
                state->window_x = SDL_WINDOWPOS_CENTERED_DISPLAY(state->displayID);
1319
                state->window_y = SDL_WINDOWPOS_CENTERED_DISPLAY(state->displayID);
1320
            }
1321
        }
1322

1323
        {
1324
            SDL_bool include_high_density_modes = SDL_FALSE;
1325
            if (state->window_flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) {
1326
                include_high_density_modes = SDL_TRUE;
1327
            }
1328
            SDL_GetClosestFullscreenDisplayMode(state->displayID, state->window_w, state->window_h, state->refresh_rate, include_high_density_modes, &state->fullscreen_mode);
1329
        }
1330

1331
        state->windows =
1332
            (SDL_Window **)SDL_calloc(state->num_windows,
1333
                                      sizeof(*state->windows));
1334
        state->renderers =
1335
            (SDL_Renderer **)SDL_calloc(state->num_windows,
1336
                                        sizeof(*state->renderers));
1337
        state->targets =
1338
            (SDL_Texture **)SDL_calloc(state->num_windows,
1339
                                       sizeof(*state->targets));
1340
        if (!state->windows || !state->renderers) {
1341
            SDL_Log("Out of memory!\n");
1342
            return SDL_FALSE;
1343
        }
1344
        for (i = 0; i < state->num_windows; ++i) {
1345
            char title[1024];
1346
            SDL_Rect r;
1347
            SDL_PropertiesID props;
1348

1349
            if (state->fill_usable_bounds) {
1350
                SDL_GetDisplayUsableBounds(state->displayID, &r);
1351
            } else {
1352
                r.x = state->window_x;
1353
                r.y = state->window_y;
1354
                r.w = state->window_w;
1355
                r.h = state->window_h;
1356
                if (state->auto_scale_content) {
1357
                    float scale = SDL_GetDisplayContentScale(state->displayID);
1358
                    r.w = (int)SDL_ceilf(r.w * scale);
1359
                    r.h = (int)SDL_ceilf(r.h * scale);
1360
                }
1361
            }
1362

1363
            if (state->num_windows > 1) {
1364
                (void)SDL_snprintf(title, SDL_arraysize(title), "%s %d",
1365
                                   state->window_title, i + 1);
1366
            } else {
1367
                SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
1368
            }
1369
            props = SDL_CreateProperties();
1370
            SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title);
1371
            SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, r.x);
1372
            SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, r.y);
1373
            SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, r.w);
1374
            SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, r.h);
1375
            SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER, state->window_flags);
1376
            state->windows[i] = SDL_CreateWindowWithProperties(props);
1377
            SDL_DestroyProperties(props);
1378
            if (!state->windows[i]) {
1379
                SDL_Log("Couldn't create window: %s\n",
1380
                        SDL_GetError());
1381
                return SDL_FALSE;
1382
            }
1383
            if (state->window_minW || state->window_minH) {
1384
                SDL_SetWindowMinimumSize(state->windows[i], state->window_minW, state->window_minH);
1385
            }
1386
            if (state->window_maxW || state->window_maxH) {
1387
                SDL_SetWindowMaximumSize(state->windows[i], state->window_maxW, state->window_maxH);
1388
            }
1389
            if (state->window_min_aspect != 0.f || state->window_max_aspect != 0.f) {
1390
                SDL_SetWindowAspectRatio(state->windows[i], state->window_min_aspect, state->window_max_aspect);
1391
            }
1392
            SDL_GetWindowSize(state->windows[i], &w, &h);
1393
            if (!(state->window_flags & SDL_WINDOW_RESIZABLE) && (w != r.w || h != r.h)) {
1394
                SDL_Log("Window requested size %dx%d, got %dx%d\n", r.w, r.h, w, h);
1395
                state->window_w = w;
1396
                state->window_h = h;
1397
            }
1398
            if (state->window_flags & SDL_WINDOW_FULLSCREEN) {
1399
                if (state->fullscreen_exclusive) {
1400
                    SDL_SetWindowFullscreenMode(state->windows[i], &state->fullscreen_mode);
1401
                }
1402
                SDL_SetWindowFullscreen(state->windows[i], SDL_TRUE);
1403
            }
1404

1405
            /* Add resize/drag areas for windows that are borderless and resizable */
1406
            if ((state->window_flags & (SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS)) ==
1407
                (SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS)) {
1408
                SDL_SetWindowHitTest(state->windows[i], SDLTest_ExampleHitTestCallback, NULL);
1409
            }
1410

1411
            if (state->window_icon) {
1412
                SDL_Surface *icon = SDLTest_LoadIcon(state->window_icon);
1413
                if (icon) {
1414
                    SDL_SetWindowIcon(state->windows[i], icon);
1415
                    SDL_DestroySurface(icon);
1416
                }
1417
            }
1418

1419
            if (!SDL_RectEmpty(&state->confine)) {
1420
                SDL_SetWindowMouseRect(state->windows[i], &state->confine);
1421
            }
1422

1423
            if (!state->skip_renderer && (state->renderdriver || !(state->window_flags & (SDL_WINDOW_OPENGL | SDL_WINDOW_VULKAN | SDL_WINDOW_METAL)))) {
1424
                state->renderers[i] = SDL_CreateRenderer(state->windows[i], state->renderdriver);
1425
                if (!state->renderers[i]) {
1426
                    SDL_Log("Couldn't create renderer: %s\n",
1427
                            SDL_GetError());
1428
                    return SDL_FALSE;
1429
                }
1430
                if (state->logical_w == 0 || state->logical_h == 0) {
1431
                    state->logical_w = state->window_w;
1432
                    state->logical_h = state->window_h;
1433
                }
1434
                if (state->render_vsync) {
1435
                    SDL_SetRenderVSync(state->renderers[i], state->render_vsync);
1436
                }
1437
                if (!SDL_SetRenderLogicalPresentation(state->renderers[i], state->logical_w, state->logical_h, state->logical_presentation, state->logical_scale_mode)) {
1438
                    SDL_Log("Couldn't set logical presentation: %s\n", SDL_GetError());
1439
                    return SDL_FALSE;
1440
                }
1441
                if (state->scale != 0.0f) {
1442
                    SDL_SetRenderScale(state->renderers[i], state->scale, state->scale);
1443
                }
1444
                if (state->verbose & VERBOSE_RENDER) {
1445
                    SDL_Log("Current renderer:\n");
1446
                    SDLTest_PrintRenderer(state->renderers[i]);
1447
                }
1448
            }
1449

1450
            SDL_ShowWindow(state->windows[i]);
1451
        }
1452
        if (state->hide_cursor) {
1453
            SDL_HideCursor();
1454
        }
1455
    }
1456

1457
    if (state->flags & SDL_INIT_AUDIO) {
1458
        if (state->verbose & VERBOSE_AUDIO) {
1459
            n = SDL_GetNumAudioDrivers();
1460
            if (n == 0) {
1461
                SDL_Log("No built-in audio drivers\n");
1462
            } else {
1463
                (void)SDL_snprintf(text, sizeof(text), "Built-in audio drivers:");
1464
                for (i = 0; i < n; ++i) {
1465
                    if (i > 0) {
1466
                        SDL_snprintfcat(text, sizeof(text), ",");
1467
                    }
1468
                    SDL_snprintfcat(text, sizeof(text), " %s", SDL_GetAudioDriver(i));
1469
                }
1470
                SDL_Log("%s\n", text);
1471
            }
1472
        }
1473
        if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) {
1474
            SDL_Log("Couldn't initialize audio driver: %s\n",
1475
                    SDL_GetError());
1476
            return SDL_FALSE;
1477
        }
1478
        if (state->verbose & VERBOSE_AUDIO) {
1479
            SDL_Log("Audio driver: %s\n",
1480
                    SDL_GetCurrentAudioDriver());
1481
        }
1482

1483
        const SDL_AudioSpec spec = { state->audio_format, state->audio_channels, state->audio_freq };
1484
        state->audio_id = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec);
1485
        if (!state->audio_id) {
1486
            SDL_Log("Couldn't open audio: %s\n", SDL_GetError());
1487
            return SDL_FALSE;
1488
        }
1489
    }
1490

1491
    if (state->flags & SDL_INIT_CAMERA) {
1492
        SDL_InitSubSystem(SDL_INIT_CAMERA);
1493
    }
1494

1495
    return SDL_TRUE;
1496
}
1497

1498
static const char *SystemThemeName(void)
1499
{
1500
    switch (SDL_GetSystemTheme()) {
1501
#define CASE(X)               \
1502
    case SDL_SYSTEM_THEME_##X: \
1503
        return #X
1504
        CASE(UNKNOWN);
1505
        CASE(LIGHT);
1506
        CASE(DARK);
1507
#undef CASE
1508
    default:
1509
        return "???";
1510
    }
1511
}
1512

1513
static const char *DisplayOrientationName(int orientation)
1514
{
1515
    switch (orientation) {
1516
#define CASE(X)               \
1517
    case SDL_ORIENTATION_##X: \
1518
        return #X
1519
        CASE(UNKNOWN);
1520
        CASE(LANDSCAPE);
1521
        CASE(LANDSCAPE_FLIPPED);
1522
        CASE(PORTRAIT);
1523
        CASE(PORTRAIT_FLIPPED);
1524
#undef CASE
1525
    default:
1526
        return "???";
1527
    }
1528
}
1529

1530
static const char *GamepadAxisName(const SDL_GamepadAxis axis)
1531
{
1532
    switch (axis) {
1533
#define AXIS_CASE(ax)              \
1534
    case SDL_GAMEPAD_AXIS_##ax: \
1535
        return #ax
1536
        AXIS_CASE(INVALID);
1537
        AXIS_CASE(LEFTX);
1538
        AXIS_CASE(LEFTY);
1539
        AXIS_CASE(RIGHTX);
1540
        AXIS_CASE(RIGHTY);
1541
        AXIS_CASE(LEFT_TRIGGER);
1542
        AXIS_CASE(RIGHT_TRIGGER);
1543
#undef AXIS_CASE
1544
    default:
1545
        return "???";
1546
    }
1547
}
1548

1549
static const char *GamepadButtonName(const SDL_GamepadButton button)
1550
{
1551
    switch (button) {
1552
#define BUTTON_CASE(btn)              \
1553
    case SDL_GAMEPAD_BUTTON_##btn: \
1554
        return #btn
1555
        BUTTON_CASE(INVALID);
1556
        BUTTON_CASE(SOUTH);
1557
        BUTTON_CASE(EAST);
1558
        BUTTON_CASE(WEST);
1559
        BUTTON_CASE(NORTH);
1560
        BUTTON_CASE(BACK);
1561
        BUTTON_CASE(GUIDE);
1562
        BUTTON_CASE(START);
1563
        BUTTON_CASE(LEFT_STICK);
1564
        BUTTON_CASE(RIGHT_STICK);
1565
        BUTTON_CASE(LEFT_SHOULDER);
1566
        BUTTON_CASE(RIGHT_SHOULDER);
1567
        BUTTON_CASE(DPAD_UP);
1568
        BUTTON_CASE(DPAD_DOWN);
1569
        BUTTON_CASE(DPAD_LEFT);
1570
        BUTTON_CASE(DPAD_RIGHT);
1571
#undef BUTTON_CASE
1572
    default:
1573
        return "???";
1574
    }
1575
}
1576

1577
void SDLTest_PrintEvent(const SDL_Event *event)
1578
{
1579
    switch (event->type) {
1580
    case SDL_EVENT_SYSTEM_THEME_CHANGED:
1581
        SDL_Log("SDL EVENT: System theme changed to %s", SystemThemeName());
1582
        break;
1583
    case SDL_EVENT_DISPLAY_ADDED:
1584
        SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " attached",
1585
                event->display.displayID);
1586
        break;
1587
    case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED:
1588
        {
1589
            float scale = SDL_GetDisplayContentScale(event->display.displayID);
1590
            SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " changed content scale to %d%%",
1591
                    event->display.displayID, (int)(scale * 100.0f));
1592
        }
1593
        break;
1594
    case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED:
1595
        SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " desktop mode changed to %" SDL_PRIs32 "x%" SDL_PRIs32,
1596
                event->display.displayID, event->display.data1, event->display.data2);
1597
        break;
1598
    case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED:
1599
        SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " current mode changed to %" SDL_PRIs32 "x%" SDL_PRIs32,
1600
                event->display.displayID, event->display.data1, event->display.data2);
1601
        break;
1602
    case SDL_EVENT_DISPLAY_MOVED:
1603
        SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " changed position",
1604
                event->display.displayID);
1605
        break;
1606
    case SDL_EVENT_DISPLAY_ORIENTATION:
1607
        SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " changed orientation to %s",
1608
                event->display.displayID, DisplayOrientationName(event->display.data1));
1609
        break;
1610
    case SDL_EVENT_DISPLAY_REMOVED:
1611
        SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " removed",
1612
                event->display.displayID);
1613
        break;
1614
    case SDL_EVENT_WINDOW_SHOWN:
1615
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " shown", event->window.windowID);
1616
        break;
1617
    case SDL_EVENT_WINDOW_HIDDEN:
1618
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " hidden", event->window.windowID);
1619
        break;
1620
    case SDL_EVENT_WINDOW_EXPOSED:
1621
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " exposed", event->window.windowID);
1622
        break;
1623
    case SDL_EVENT_WINDOW_MOVED:
1624
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " moved to %" SDL_PRIs32 ",%" SDL_PRIs32,
1625
                event->window.windowID, event->window.data1, event->window.data2);
1626
        break;
1627
    case SDL_EVENT_WINDOW_RESIZED:
1628
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " resized to %" SDL_PRIs32 "x%" SDL_PRIs32,
1629
                event->window.windowID, event->window.data1, event->window.data2);
1630
        break;
1631
    case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
1632
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " changed pixel size to %" SDL_PRIs32 "x%" SDL_PRIs32,
1633
                event->window.windowID, event->window.data1, event->window.data2);
1634
        break;
1635
    case SDL_EVENT_WINDOW_METAL_VIEW_RESIZED:
1636
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " changed metal view size",
1637
                event->window.windowID);
1638
        break;
1639
    case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED: {
1640
        SDL_Rect rect;
1641

1642
        SDL_GetWindowSafeArea(SDL_GetWindowFromEvent(event), &rect);
1643
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " changed safe area to: %d,%d %dx%d\n",
1644
                event->window.windowID, rect.x, rect.y, rect.w, rect.h);
1645
        break;
1646
    }
1647
    case SDL_EVENT_WINDOW_MINIMIZED:
1648
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " minimized", event->window.windowID);
1649
        break;
1650
    case SDL_EVENT_WINDOW_MAXIMIZED:
1651
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " maximized", event->window.windowID);
1652
        break;
1653
    case SDL_EVENT_WINDOW_RESTORED:
1654
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " restored", event->window.windowID);
1655
        break;
1656
    case SDL_EVENT_WINDOW_MOUSE_ENTER:
1657
        SDL_Log("SDL EVENT: Mouse entered window %" SDL_PRIu32, event->window.windowID);
1658
        break;
1659
    case SDL_EVENT_WINDOW_MOUSE_LEAVE:
1660
        SDL_Log("SDL EVENT: Mouse left window %" SDL_PRIu32, event->window.windowID);
1661
        break;
1662
    case SDL_EVENT_WINDOW_FOCUS_GAINED:
1663
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " gained keyboard focus",
1664
                event->window.windowID);
1665
        break;
1666
    case SDL_EVENT_WINDOW_FOCUS_LOST:
1667
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " lost keyboard focus",
1668
                event->window.windowID);
1669
        break;
1670
    case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
1671
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " closed", event->window.windowID);
1672
        break;
1673
    case SDL_EVENT_WINDOW_HIT_TEST:
1674
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " hit test", event->window.windowID);
1675
        break;
1676
    case SDL_EVENT_WINDOW_ICCPROF_CHANGED:
1677
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " ICC profile changed", event->window.windowID);
1678
        break;
1679
    case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
1680
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " display changed to %" SDL_PRIs32, event->window.windowID, event->window.data1);
1681
        break;
1682
    case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
1683
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " display scale changed to %d%%", event->window.windowID, (int)(SDL_GetWindowDisplayScale(SDL_GetWindowFromEvent(event)) * 100.0f));
1684
        break;
1685
    case SDL_EVENT_WINDOW_OCCLUDED:
1686
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " occluded", event->window.windowID);
1687
        break;
1688
    case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
1689
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " entered fullscreen", event->window.windowID);
1690
        break;
1691
    case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
1692
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " left fullscreen", event->window.windowID);
1693
        break;
1694
    case SDL_EVENT_WINDOW_DESTROYED:
1695
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " destroyed", event->window.windowID);
1696
        break;
1697
    case SDL_EVENT_WINDOW_HDR_STATE_CHANGED:
1698
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " HDR %s", event->window.windowID, event->window.data1 ? "enabled" : "disabled");
1699
        break;
1700
    case SDL_EVENT_KEYBOARD_ADDED:
1701
        SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " attached",
1702
                event->kdevice.which);
1703
        break;
1704
    case SDL_EVENT_KEYBOARD_REMOVED:
1705
        SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " removed",
1706
                event->kdevice.which);
1707
        break;
1708
    case SDL_EVENT_KEY_DOWN:
1709
    case SDL_EVENT_KEY_UP: {
1710
        char modstr[64];
1711
        if (event->key.mod) {
1712
            modstr[0] = '\0';
1713
            SDLTest_PrintModState(modstr, sizeof (modstr), event->key.mod);
1714
        } else {
1715
            SDL_strlcpy(modstr, "NONE", sizeof (modstr));
1716
        }
1717

1718
        SDL_Log("SDL EVENT: Keyboard: key %s in window %" SDL_PRIu32 ": scancode 0x%08X = %s, keycode 0x%08" SDL_PRIX32 " = %s, mods = %s",
1719
                (event->type == SDL_EVENT_KEY_DOWN) ? "pressed" : "released",
1720
                event->key.windowID,
1721
                event->key.scancode,
1722
                SDL_GetScancodeName(event->key.scancode),
1723
                event->key.key, SDL_GetKeyName(event->key.key),
1724
                modstr);
1725
        break;
1726
    }
1727
    case SDL_EVENT_TEXT_EDITING:
1728
        SDL_Log("SDL EVENT: Keyboard: text editing \"%s\" in window %" SDL_PRIu32,
1729
                event->edit.text, event->edit.windowID);
1730
        break;
1731
    case SDL_EVENT_TEXT_INPUT:
1732
        SDL_Log("SDL EVENT: Keyboard: text input \"%s\" in window %" SDL_PRIu32,
1733
                event->text.text, event->text.windowID);
1734
        break;
1735
    case SDL_EVENT_KEYMAP_CHANGED:
1736
        SDL_Log("SDL EVENT: Keymap changed");
1737
        break;
1738
    case SDL_EVENT_MOUSE_ADDED:
1739
        SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " attached",
1740
                event->mdevice.which);
1741
        break;
1742
    case SDL_EVENT_MOUSE_REMOVED:
1743
        SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " removed",
1744
                event->mdevice.which);
1745
        break;
1746
    case SDL_EVENT_MOUSE_MOTION:
1747
        SDL_Log("SDL EVENT: Mouse: moved to %g,%g (%g,%g) in window %" SDL_PRIu32,
1748
                event->motion.x, event->motion.y,
1749
                event->motion.xrel, event->motion.yrel,
1750
                event->motion.windowID);
1751
        break;
1752
    case SDL_EVENT_MOUSE_BUTTON_DOWN:
1753
        SDL_Log("SDL EVENT: Mouse: button %d pressed at %g,%g with click count %d in window %" SDL_PRIu32,
1754
                event->button.button, event->button.x, event->button.y, event->button.clicks,
1755
                event->button.windowID);
1756
        break;
1757
    case SDL_EVENT_MOUSE_BUTTON_UP:
1758
        SDL_Log("SDL EVENT: Mouse: button %d released at %g,%g with click count %d in window %" SDL_PRIu32,
1759
                event->button.button, event->button.x, event->button.y, event->button.clicks,
1760
                event->button.windowID);
1761
        break;
1762
    case SDL_EVENT_MOUSE_WHEEL:
1763
        SDL_Log("SDL EVENT: Mouse: wheel scrolled %g in x and %g in y (reversed: %d) in window %" SDL_PRIu32,
1764
                event->wheel.x, event->wheel.y, event->wheel.direction, event->wheel.windowID);
1765
        break;
1766
    case SDL_EVENT_JOYSTICK_ADDED:
1767
        SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " attached",
1768
                event->jdevice.which);
1769
        break;
1770
    case SDL_EVENT_JOYSTICK_REMOVED:
1771
        SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " removed",
1772
                event->jdevice.which);
1773
        break;
1774
    case SDL_EVENT_JOYSTICK_BALL_MOTION:
1775
        SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 ": ball %d moved by %d,%d",
1776
                event->jball.which, event->jball.ball, event->jball.xrel,
1777
                event->jball.yrel);
1778
        break;
1779
    case SDL_EVENT_JOYSTICK_HAT_MOTION:
1780
    {
1781
        const char *position = "UNKNOWN";
1782
        switch (event->jhat.value) {
1783
        case SDL_HAT_CENTERED:
1784
            position = "CENTER";
1785
            break;
1786
        case SDL_HAT_UP:
1787
            position = "UP";
1788
            break;
1789
        case SDL_HAT_RIGHTUP:
1790
            position = "RIGHTUP";
1791
            break;
1792
        case SDL_HAT_RIGHT:
1793
            position = "RIGHT";
1794
            break;
1795
        case SDL_HAT_RIGHTDOWN:
1796
            position = "RIGHTDOWN";
1797
            break;
1798
        case SDL_HAT_DOWN:
1799
            position = "DOWN";
1800
            break;
1801
        case SDL_HAT_LEFTDOWN:
1802
            position = "LEFTDOWN";
1803
            break;
1804
        case SDL_HAT_LEFT:
1805
            position = "LEFT";
1806
            break;
1807
        case SDL_HAT_LEFTUP:
1808
            position = "LEFTUP";
1809
            break;
1810
        }
1811
        SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 ": hat %d moved to %s",
1812
                event->jhat.which, event->jhat.hat, position);
1813
    } break;
1814
    case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
1815
        SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 ": button %d pressed",
1816
                event->jbutton.which, event->jbutton.button);
1817
        break;
1818
    case SDL_EVENT_JOYSTICK_BUTTON_UP:
1819
        SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 ": button %d released",
1820
                event->jbutton.which, event->jbutton.button);
1821
        break;
1822
    case SDL_EVENT_GAMEPAD_ADDED:
1823
        SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " attached",
1824
                event->gdevice.which);
1825
        break;
1826
    case SDL_EVENT_GAMEPAD_REMOVED:
1827
        SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " removed",
1828
                event->gdevice.which);
1829
        break;
1830
    case SDL_EVENT_GAMEPAD_AXIS_MOTION:
1831
        SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " axis %d ('%s') value: %d",
1832
                event->gaxis.which,
1833
                event->gaxis.axis,
1834
                GamepadAxisName((SDL_GamepadAxis)event->gaxis.axis),
1835
                event->gaxis.value);
1836
        break;
1837
    case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
1838
        SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 "button %d ('%s') down",
1839
                event->gbutton.which, event->gbutton.button,
1840
                GamepadButtonName((SDL_GamepadButton)event->gbutton.button));
1841
        break;
1842
    case SDL_EVENT_GAMEPAD_BUTTON_UP:
1843
        SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " button %d ('%s') up",
1844
                event->gbutton.which, event->gbutton.button,
1845
                GamepadButtonName((SDL_GamepadButton)event->gbutton.button));
1846
        break;
1847
    case SDL_EVENT_CLIPBOARD_UPDATE:
1848
        SDL_Log("SDL EVENT: Clipboard updated");
1849
        break;
1850

1851
    case SDL_EVENT_FINGER_MOTION:
1852
        SDL_Log("SDL EVENT: Finger: motion touch=%" SDL_PRIu64 ", finger=%" SDL_PRIu64 ", x=%f, y=%f, dx=%f, dy=%f, pressure=%f",
1853
                event->tfinger.touchID,
1854
                event->tfinger.fingerID,
1855
                event->tfinger.x, event->tfinger.y,
1856
                event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
1857
        break;
1858
    case SDL_EVENT_FINGER_DOWN:
1859
    case SDL_EVENT_FINGER_UP:
1860
        SDL_Log("SDL EVENT: Finger: %s touch=%" SDL_PRIu64 ", finger=%" SDL_PRIu64 ", x=%f, y=%f, dx=%f, dy=%f, pressure=%f",
1861
                (event->type == SDL_EVENT_FINGER_DOWN) ? "down" : "up",
1862
                event->tfinger.touchID,
1863
                event->tfinger.fingerID,
1864
                event->tfinger.x, event->tfinger.y,
1865
                event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
1866
        break;
1867

1868
    case SDL_EVENT_RENDER_DEVICE_RESET:
1869
        SDL_Log("SDL EVENT: render device reset");
1870
        break;
1871
    case SDL_EVENT_RENDER_TARGETS_RESET:
1872
        SDL_Log("SDL EVENT: render targets reset");
1873
        break;
1874

1875
    case SDL_EVENT_TERMINATING:
1876
        SDL_Log("SDL EVENT: App terminating");
1877
        break;
1878
    case SDL_EVENT_LOW_MEMORY:
1879
        SDL_Log("SDL EVENT: App running low on memory");
1880
        break;
1881
    case SDL_EVENT_WILL_ENTER_BACKGROUND:
1882
        SDL_Log("SDL EVENT: App will enter the background");
1883
        break;
1884
    case SDL_EVENT_DID_ENTER_BACKGROUND:
1885
        SDL_Log("SDL EVENT: App entered the background");
1886
        break;
1887
    case SDL_EVENT_WILL_ENTER_FOREGROUND:
1888
        SDL_Log("SDL EVENT: App will enter the foreground");
1889
        break;
1890
    case SDL_EVENT_DID_ENTER_FOREGROUND:
1891
        SDL_Log("SDL EVENT: App entered the foreground");
1892
        break;
1893
    case SDL_EVENT_DROP_BEGIN:
1894
        SDL_Log("SDL EVENT: Drag and drop beginning in window %" SDL_PRIu32, event->drop.windowID);
1895
        break;
1896
    case SDL_EVENT_DROP_POSITION:
1897
        SDL_Log("SDL EVENT: Drag and drop moving in window %" SDL_PRIu32 ": %g,%g", event->drop.windowID, event->drop.x, event->drop.y);
1898
        break;
1899
    case SDL_EVENT_DROP_FILE:
1900
        SDL_Log("SDL EVENT: Drag and drop file in window %" SDL_PRIu32 ": '%s'", event->drop.windowID, event->drop.data);
1901
        break;
1902
    case SDL_EVENT_DROP_TEXT:
1903
        SDL_Log("SDL EVENT: Drag and drop text in window %" SDL_PRIu32 ": '%s'", event->drop.windowID, event->drop.data);
1904
        break;
1905
    case SDL_EVENT_DROP_COMPLETE:
1906
        SDL_Log("SDL EVENT: Drag and drop ending");
1907
        break;
1908
    case SDL_EVENT_QUIT:
1909
        SDL_Log("SDL EVENT: Quit requested");
1910
        break;
1911
    case SDL_EVENT_USER:
1912
        SDL_Log("SDL EVENT: User event %" SDL_PRIs32, event->user.code);
1913
        break;
1914
    default:
1915
        SDL_Log("Unknown event 0x%4.4" SDL_PRIu32, event->type);
1916
        break;
1917
    }
1918
}
1919

1920
#define SCREENSHOT_FILE "screenshot.bmp"
1921

1922
typedef struct
1923
{
1924
    void *image;
1925
    size_t size;
1926
} SDLTest_ClipboardData;
1927

1928
static void SDLTest_ScreenShotClipboardCleanup(void *context)
1929
{
1930
    SDLTest_ClipboardData *data = (SDLTest_ClipboardData *)context;
1931

1932
    SDL_Log("Cleaning up screenshot image data\n");
1933

1934
    if (data->image) {
1935
        SDL_free(data->image);
1936
    }
1937
    SDL_free(data);
1938
}
1939

1940
static const void *SDLTest_ScreenShotClipboardProvider(void *context, const char *mime_type, size_t *size)
1941
{
1942
    SDLTest_ClipboardData *data = (SDLTest_ClipboardData *)context;
1943

1944
    if (SDL_strncmp(mime_type, "text", 4) == 0) {
1945
        SDL_Log("Providing screenshot title to clipboard!\n");
1946

1947
        /* Return "Test screenshot" */
1948
        *size = 15;
1949
        return "Test screenshot (but this isn't part of it)";
1950
    }
1951

1952
    SDL_Log("Providing screenshot image to clipboard!\n");
1953

1954
    if (!data->image) {
1955
        SDL_IOStream *file;
1956

1957
        file = SDL_IOFromFile(SCREENSHOT_FILE, "r");
1958
        if (file) {
1959
            size_t length = (size_t)SDL_GetIOSize(file);
1960
            void *image = SDL_malloc(length);
1961
            if (image) {
1962
                if (SDL_ReadIO(file, image, length) != length) {
1963
                    SDL_Log("Couldn't read %s: %s\n", SCREENSHOT_FILE, SDL_GetError());
1964
                    SDL_free(image);
1965
                    image = NULL;
1966
                }
1967
            }
1968
            SDL_CloseIO(file);
1969

1970
            if (image) {
1971
                data->image = image;
1972
                data->size = length;
1973
            }
1974
        } else {
1975
            SDL_Log("Couldn't load %s: %s\n", SCREENSHOT_FILE, SDL_GetError());
1976
        }
1977
    }
1978

1979
    *size = data->size;
1980
    return data->image;
1981
}
1982

1983
static void SDLTest_CopyScreenShot(SDL_Renderer *renderer)
1984
{
1985
    SDL_Surface *surface;
1986
    const char *image_formats[] = {
1987
        "text/plain;charset=utf-8",
1988
        "image/bmp"
1989
    };
1990
    SDLTest_ClipboardData *clipboard_data;
1991

1992
    if (!renderer) {
1993
        return;
1994
    }
1995

1996
    surface = SDL_RenderReadPixels(renderer, NULL);
1997
    if (!surface) {
1998
        SDL_Log("Couldn't read screen: %s\n", SDL_GetError());
1999
        return;
2000
    }
2001

2002
    if (!SDL_SaveBMP(surface, SCREENSHOT_FILE)) {
2003
        SDL_Log("Couldn't save %s: %s\n", SCREENSHOT_FILE, SDL_GetError());
2004
        SDL_DestroySurface(surface);
2005
        return;
2006
    }
2007
    SDL_DestroySurface(surface);
2008

2009
    clipboard_data = (SDLTest_ClipboardData *)SDL_calloc(1, sizeof(*clipboard_data));
2010
    if (!clipboard_data) {
2011
        SDL_Log("Couldn't allocate clipboard data\n");
2012
        return;
2013
    }
2014
    SDL_SetClipboardData(SDLTest_ScreenShotClipboardProvider, SDLTest_ScreenShotClipboardCleanup, clipboard_data, image_formats, SDL_arraysize(image_formats));
2015
    SDL_Log("Saved screenshot to %s and clipboard\n", SCREENSHOT_FILE);
2016
}
2017

2018
static void SDLTest_PasteScreenShot(void)
2019
{
2020
    const char *image_formats[] = {
2021
        "image/bmp",
2022
        "image/png",
2023
        "image/tiff",
2024
    };
2025
    size_t i;
2026

2027
    for (i = 0; i < SDL_arraysize(image_formats); ++i) {
2028
        size_t size;
2029
        void *data = SDL_GetClipboardData(image_formats[i], &size);
2030
        if (data) {
2031
            char filename[16];
2032
            SDL_IOStream *file;
2033

2034
            SDL_snprintf(filename, sizeof(filename), "clipboard.%s", image_formats[i] + 6);
2035
            file = SDL_IOFromFile(filename, "w");
2036
            if (file) {
2037
                SDL_Log("Writing clipboard image to %s", filename);
2038
                SDL_WriteIO(file, data, size);
2039
                SDL_CloseIO(file);
2040
            }
2041
            SDL_free(data);
2042
            return;
2043
        }
2044
    }
2045
    SDL_Log("No supported screenshot data in the clipboard");
2046
}
2047

2048
static void FullscreenTo(SDLTest_CommonState *state, int index, int windowId)
2049
{
2050
    int num_displays;
2051
    SDL_DisplayID *displays;
2052
    SDL_Window *window;
2053
    SDL_WindowFlags flags;
2054
    const SDL_DisplayMode *mode;
2055
    struct SDL_Rect rect = { 0, 0, 0, 0 };
2056

2057
    displays = SDL_GetDisplays(&num_displays);
2058
    if (displays && index < num_displays) {
2059
        window = SDL_GetWindowFromID(windowId);
2060
        if (window) {
2061
            SDL_GetDisplayBounds(displays[index], &rect);
2062

2063
            flags = SDL_GetWindowFlags(window);
2064
            if (flags & SDL_WINDOW_FULLSCREEN) {
2065
                SDL_SetWindowFullscreen(window, SDL_FALSE);
2066
                SDL_Delay(15);
2067
            }
2068

2069
            mode = SDL_GetWindowFullscreenMode(window);
2070
            if (mode) {
2071
                /* Try to set the existing mode on the new display */
2072
                SDL_DisplayMode new_mode;
2073

2074
                SDL_memcpy(&new_mode, mode, sizeof(new_mode));
2075
                new_mode.displayID = displays[index];
2076
                if (!SDL_SetWindowFullscreenMode(window, &new_mode)) {
2077
                    /* Try again with a default mode */
2078
                    SDL_bool include_high_density_modes = SDL_FALSE;
2079
                    if (state->window_flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) {
2080
                        include_high_density_modes = SDL_TRUE;
2081
                    }
2082
                    if (SDL_GetClosestFullscreenDisplayMode(displays[index], state->window_w, state->window_h, state->refresh_rate, include_high_density_modes, &new_mode)) {
2083
                        SDL_SetWindowFullscreenMode(window, &new_mode);
2084
                    }
2085
                }
2086
            }
2087
            if (!mode) {
2088
                SDL_SetWindowPosition(window, rect.x, rect.y);
2089
            }
2090
            SDL_SetWindowFullscreen(window, SDL_TRUE);
2091
        }
2092
    }
2093
    SDL_free(displays);
2094
}
2095

2096
SDL_AppResult SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event *event)
2097
{
2098
    int i;
2099

2100
    if (state->verbose & VERBOSE_EVENT) {
2101
        if (((event->type != SDL_EVENT_MOUSE_MOTION) &&
2102
             (event->type != SDL_EVENT_FINGER_MOTION)) ||
2103
            (state->verbose & VERBOSE_MOTION)) {
2104
            SDLTest_PrintEvent(event);
2105
        }
2106
    }
2107

2108
    switch (event->type) {
2109
    case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
2110
        if (state->auto_scale_content) {
2111
            SDL_Window *window = SDL_GetWindowFromEvent(event);
2112
            if (window) {
2113
                float scale = SDL_GetDisplayContentScale(SDL_GetDisplayForWindow(window));
2114
                int w = state->window_w;
2115
                int h = state->window_h;
2116

2117
                w = (int)SDL_ceilf(w * scale);
2118
                h = (int)SDL_ceilf(h * scale);
2119
                SDL_SetWindowSize(window, w, h);
2120
            }
2121
        }
2122
        break;
2123
    case SDL_EVENT_WINDOW_FOCUS_LOST:
2124
        if (state->flash_on_focus_loss) {
2125
            SDL_Window *window = SDL_GetWindowFromEvent(event);
2126
            if (window) {
2127
                SDL_FlashWindow(window, SDL_FLASH_UNTIL_FOCUSED);
2128
            }
2129
        }
2130
        break;
2131
    case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
2132
    {
2133
        SDL_Window *window = SDL_GetWindowFromEvent(event);
2134
        if (window) {
2135
            SDL_HideWindow(window);
2136
        }
2137
        break;
2138
    }
2139
    case SDL_EVENT_KEY_DOWN:
2140
    {
2141
        SDL_bool withControl = !!(event->key.mod & SDL_KMOD_CTRL);
2142
        SDL_bool withShift = !!(event->key.mod & SDL_KMOD_SHIFT);
2143
        SDL_bool withAlt = !!(event->key.mod & SDL_KMOD_ALT);
2144

2145
        switch (event->key.key) {
2146
            /* Add hotkeys here */
2147
        case SDLK_PRINTSCREEN:
2148
        {
2149
            SDL_Window *window = SDL_GetWindowFromEvent(event);
2150
            if (window) {
2151
                for (i = 0; i < state->num_windows; ++i) {
2152
                    if (window == state->windows[i]) {
2153
                        SDLTest_CopyScreenShot(state->renderers[i]);
2154
                    }
2155
                }
2156
            }
2157
        } break;
2158
        case SDLK_EQUALS:
2159
            if (withControl) {
2160
                /* Ctrl-+ double the size of the window */
2161
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2162
                if (window) {
2163
                    int w, h;
2164
                    SDL_GetWindowSize(window, &w, &h);
2165
                    SDL_SetWindowSize(window, w * 2, h * 2);
2166
                }
2167
            }
2168
            break;
2169
        case SDLK_MINUS:
2170
            if (withControl) {
2171
                /* Ctrl-- half the size of the window */
2172
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2173
                if (window) {
2174
                    int w, h;
2175
                    SDL_GetWindowSize(window, &w, &h);
2176
                    SDL_SetWindowSize(window, w / 2, h / 2);
2177
                }
2178
            }
2179
            break;
2180
        case SDLK_UP:
2181
        case SDLK_DOWN:
2182
        case SDLK_LEFT:
2183
        case SDLK_RIGHT:
2184
            if (withAlt) {
2185
                /* Alt-Up/Down/Left/Right switches between displays */
2186
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2187
                if (window) {
2188
                    int num_displays;
2189
                    const SDL_DisplayID *displays = SDL_GetDisplays(&num_displays);
2190
                    if (displays) {
2191
                        SDL_DisplayID displayID = SDL_GetDisplayForWindow(window);
2192
                        int current_index = -1;
2193

2194
                        for (i = 0; i < num_displays; ++i) {
2195
                            if (displayID == displays[i]) {
2196
                                current_index = i;
2197
                                break;
2198
                            }
2199
                        }
2200
                        if (current_index >= 0) {
2201
                            SDL_DisplayID dest;
2202
                            if (event->key.key == SDLK_UP || event->key.key == SDLK_LEFT) {
2203
                                dest = displays[(current_index + num_displays - 1) % num_displays];
2204
                            } else {
2205
                                dest = displays[(current_index + num_displays + 1) % num_displays];
2206
                            }
2207
                            SDL_Log("Centering on display (%" SDL_PRIu32 ")\n", dest);
2208
                            SDL_SetWindowPosition(window,
2209
                                                  SDL_WINDOWPOS_CENTERED_DISPLAY(dest),
2210
                                                  SDL_WINDOWPOS_CENTERED_DISPLAY(dest));
2211
                        }
2212
                    }
2213
                }
2214
            }
2215
            if (withShift) {
2216
                /* Shift-Up/Down/Left/Right shift the window by 100px */
2217
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2218
                if (window) {
2219
                    const int delta = 100;
2220
                    int x, y;
2221
                    SDL_GetWindowPosition(window, &x, &y);
2222

2223
                    if (event->key.key == SDLK_UP) {
2224
                        y -= delta;
2225
                    }
2226
                    if (event->key.key == SDLK_DOWN) {
2227
                        y += delta;
2228
                    }
2229
                    if (event->key.key == SDLK_LEFT) {
2230
                        x -= delta;
2231
                    }
2232
                    if (event->key.key == SDLK_RIGHT) {
2233
                        x += delta;
2234
                    }
2235

2236
                    SDL_Log("Setting position to (%d, %d)\n", x, y);
2237
                    SDL_SetWindowPosition(window, x, y);
2238
                }
2239
            }
2240
            break;
2241
        case SDLK_O:
2242
            if (withControl) {
2243
                /* Ctrl-O (or Ctrl-Shift-O) changes window opacity. */
2244
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2245
                if (window) {
2246
                    float opacity = SDL_GetWindowOpacity(window);
2247
                    if (withShift) {
2248
                        opacity += 0.20f;
2249
                    } else {
2250
                        opacity -= 0.20f;
2251
                    }
2252
                    SDL_SetWindowOpacity(window, opacity);
2253
                }
2254
            }
2255
            break;
2256
        case SDLK_H:
2257
            if (withControl) {
2258
                /* Ctrl-H changes cursor visibility. */
2259
                if (SDL_CursorVisible()) {
2260
                    SDL_HideCursor();
2261
                } else {
2262
                    SDL_ShowCursor();
2263
                }
2264
            }
2265
            break;
2266
        case SDLK_C:
2267
            if (withAlt) {
2268
                /* Alt-C copy awesome text to the primary selection! */
2269
                SDL_SetPrimarySelectionText("SDL rocks!\nYou know it!");
2270
                SDL_Log("Copied text to primary selection\n");
2271

2272
            } else if (withControl) {
2273
                if (withShift) {
2274
                    /* Ctrl-Shift-C copy screenshot! */
2275
                    SDL_Window *window = SDL_GetWindowFromEvent(event);
2276
                    if (window) {
2277
                        for (i = 0; i < state->num_windows; ++i) {
2278
                            if (window == state->windows[i]) {
2279
                                SDLTest_CopyScreenShot(state->renderers[i]);
2280
                            }
2281
                        }
2282
                    }
2283
                } else {
2284
                    /* Ctrl-C copy awesome text! */
2285
                    SDL_SetClipboardText("SDL rocks!\nYou know it!");
2286
                    SDL_Log("Copied text to clipboard\n");
2287
                }
2288
                break;
2289
            }
2290
            break;
2291
        case SDLK_V:
2292
            if (withAlt) {
2293
                /* Alt-V paste awesome text from the primary selection! */
2294
                char *text = SDL_GetPrimarySelectionText();
2295
                if (*text) {
2296
                    SDL_Log("Primary selection: %s\n", text);
2297
                } else {
2298
                    SDL_Log("Primary selection is empty\n");
2299
                }
2300
                SDL_free(text);
2301

2302
            } else if (withControl) {
2303
                if (withShift) {
2304
                    /* Ctrl-Shift-V paste screenshot! */
2305
                    SDLTest_PasteScreenShot();
2306
                } else {
2307
                    /* Ctrl-V paste awesome text! */
2308
                    char *text = SDL_GetClipboardText();
2309
                    if (*text) {
2310
                        SDL_Log("Clipboard: %s\n", text);
2311
                    } else {
2312
                        SDL_Log("Clipboard is empty\n");
2313
                    }
2314
                    SDL_free(text);
2315
                }
2316
            }
2317
            break;
2318
        case SDLK_F:
2319
            if (withControl) {
2320
                /* Ctrl-F flash the window */
2321
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2322
                if (window) {
2323
                    SDL_FlashWindow(window, SDL_FLASH_BRIEFLY);
2324
                }
2325
            }
2326
            break;
2327
        case SDLK_G:
2328
            if (withControl) {
2329
                /* Ctrl-G toggle mouse grab */
2330
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2331
                if (window) {
2332
                    SDL_SetWindowMouseGrab(window, !SDL_GetWindowMouseGrab(window));
2333
                }
2334
            }
2335
            break;
2336
        case SDLK_K:
2337
            if (withControl) {
2338
                /* Ctrl-K toggle keyboard grab */
2339
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2340
                if (window) {
2341
                    SDL_SetWindowKeyboardGrab(window, !SDL_GetWindowKeyboardGrab(window));
2342
                }
2343
            }
2344
            break;
2345
        case SDLK_M:
2346
            if (withControl) {
2347
                /* Ctrl-M maximize */
2348
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2349
                if (window) {
2350
                    SDL_WindowFlags flags = SDL_GetWindowFlags(window);
2351
                    if (flags & SDL_WINDOW_MAXIMIZED) {
2352
                        SDL_RestoreWindow(window);
2353
                    } else {
2354
                        SDL_MaximizeWindow(window);
2355
                    }
2356
                }
2357
            }
2358
            if (withShift) {
2359
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2360
                if (window) {
2361
                    const SDL_bool shouldCapture = !(SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE);
2362
                    const SDL_bool rc = SDL_CaptureMouse(shouldCapture);
2363
                    SDL_Log("%sapturing mouse %s!\n", shouldCapture ? "C" : "Unc", rc ? "succeeded" : "failed");
2364
                }
2365
            }
2366
            break;
2367
        case SDLK_R:
2368
            if (withControl) {
2369
                /* Ctrl-R toggle mouse relative mode */
2370
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2371
                if (window) {
2372
                    SDL_SetWindowRelativeMouseMode(window, !SDL_GetWindowRelativeMouseMode(window));
2373
                }
2374
            }
2375
            break;
2376
        case SDLK_T:
2377
            if (withControl) {
2378
                /* Ctrl-T toggle topmost mode */
2379
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2380
                if (window) {
2381
                    SDL_WindowFlags flags = SDL_GetWindowFlags(window);
2382
                    if (flags & SDL_WINDOW_ALWAYS_ON_TOP) {
2383
                        SDL_SetWindowAlwaysOnTop(window, SDL_FALSE);
2384
                    } else {
2385
                        SDL_SetWindowAlwaysOnTop(window, SDL_TRUE);
2386
                    }
2387
                }
2388
            }
2389
            break;
2390
        case SDLK_Z:
2391
            if (withControl) {
2392
                /* Ctrl-Z minimize */
2393
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2394
                if (window) {
2395
                    SDL_MinimizeWindow(window);
2396
                }
2397
            }
2398
            break;
2399
        case SDLK_RETURN:
2400
            if (withControl) {
2401
                /* Ctrl-Enter toggle fullscreen */
2402
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2403
                if (window) {
2404
                    SDL_WindowFlags flags = SDL_GetWindowFlags(window);
2405
                    if (!(flags & SDL_WINDOW_FULLSCREEN) ||
2406
                        !SDL_GetWindowFullscreenMode(window)) {
2407
                        SDL_SetWindowFullscreenMode(window, &state->fullscreen_mode);
2408
                        SDL_SetWindowFullscreen(window, SDL_TRUE);
2409
                    } else {
2410
                        SDL_SetWindowFullscreen(window, SDL_FALSE);
2411
                    }
2412
                }
2413
            } else if (withAlt) {
2414
                /* Alt-Enter toggle fullscreen desktop */
2415
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2416
                if (window) {
2417
                    SDL_WindowFlags flags = SDL_GetWindowFlags(window);
2418
                    if (!(flags & SDL_WINDOW_FULLSCREEN) ||
2419
                        SDL_GetWindowFullscreenMode(window)) {
2420
                        SDL_SetWindowFullscreenMode(window, NULL);
2421
                        SDL_SetWindowFullscreen(window, SDL_TRUE);
2422
                    } else {
2423
                        SDL_SetWindowFullscreen(window, SDL_FALSE);
2424
                    }
2425
                }
2426
            }
2427

2428
            break;
2429
        case SDLK_B:
2430
            if (withControl) {
2431
                /* Ctrl-B toggle window border */
2432
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2433
                if (window) {
2434
                    const SDL_WindowFlags flags = SDL_GetWindowFlags(window);
2435
                    const SDL_bool b = (flags & SDL_WINDOW_BORDERLESS) ? SDL_TRUE : SDL_FALSE;
2436
                    SDL_SetWindowBordered(window, b);
2437
                }
2438
            }
2439
            break;
2440
        case SDLK_A:
2441
            if (withControl) {
2442
                /* Ctrl-A toggle aspect ratio */
2443
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2444
                if (window) {
2445
                    float min_aspect = 0.0f, max_aspect = 0.0f;
2446

2447
                    SDL_GetWindowAspectRatio(window, &min_aspect, &max_aspect);
2448
                    if (min_aspect > 0.0f || max_aspect > 0.0f) {
2449
                        min_aspect = 0.0f;
2450
                        max_aspect = 0.0f;
2451
                    } else {
2452
                        min_aspect = 1.0f;
2453
                        max_aspect = 1.0f;
2454
                    }
2455
                    SDL_SetWindowAspectRatio(window, min_aspect, max_aspect);
2456
                }
2457
            }
2458
            break;
2459
        case SDLK_0:
2460
            if (withControl) {
2461
                SDL_Window *window = SDL_GetWindowFromEvent(event);
2462
                SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Test Message", "You're awesome!", window);
2463
            }
2464
            break;
2465
        case SDLK_1:
2466
            if (withControl) {
2467
                FullscreenTo(state, 0, event->key.windowID);
2468
            }
2469
            break;
2470
        case SDLK_2:
2471
            if (withControl) {
2472
                FullscreenTo(state, 1, event->key.windowID);
2473
            }
2474
            break;
2475
        case SDLK_ESCAPE:
2476
            return SDL_APP_SUCCESS;
2477
        default:
2478
            break;
2479
        }
2480
        break;
2481
    }
2482
    case SDL_EVENT_QUIT:
2483
        return SDL_APP_SUCCESS;
2484
    default:
2485
        break;
2486
    }
2487

2488
    return SDL_APP_CONTINUE;
2489
}
2490

2491
void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done)
2492
{
2493
    if (SDLTest_CommonEventMainCallbacks(state, event) != SDL_APP_CONTINUE) {
2494
        *done = 1;
2495
    }
2496
}
2497

2498
void SDLTest_CommonQuit(SDLTest_CommonState *state)
2499
{
2500
    int i;
2501

2502
    SDL_free(common_usage_video);
2503
    SDL_free(common_usage_audio);
2504
    SDL_free(common_usage_videoaudio);
2505
    common_usage_video = NULL;
2506
    common_usage_audio = NULL;
2507
    common_usage_videoaudio = NULL;
2508

2509
    if (state->targets) {
2510
        for (i = 0; i < state->num_windows; ++i) {
2511
            if (state->targets[i]) {
2512
                SDL_DestroyTexture(state->targets[i]);
2513
            }
2514
        }
2515
        SDL_free(state->targets);
2516
    }
2517
    if (state->renderers) {
2518
        for (i = 0; i < state->num_windows; ++i) {
2519
            if (state->renderers[i]) {
2520
                SDL_DestroyRenderer(state->renderers[i]);
2521
            }
2522
        }
2523
        SDL_free(state->renderers);
2524
    }
2525
    if (state->windows) {
2526
        for (i = 0; i < state->num_windows; i++) {
2527
            SDL_DestroyWindow(state->windows[i]);
2528
        }
2529
        SDL_free(state->windows);
2530
    }
2531
    SDL_Quit();
2532
    SDLTest_CommonDestroyState(state);
2533
}
2534

2535
void SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, float *usedHeight)
2536
{
2537
    char text[1024];
2538
    float textY = 0.0f;
2539
    const int lineHeight = 10;
2540
    int x, y, w, h;
2541
    float fx, fy;
2542
    SDL_Rect rect;
2543
    const SDL_DisplayMode *mode;
2544
    float scaleX, scaleY;
2545
    SDL_MouseButtonFlags flags;
2546
    SDL_DisplayID windowDisplayID = SDL_GetDisplayForWindow(window);
2547
    const char *name;
2548
    SDL_RendererLogicalPresentation logical_presentation;
2549
    SDL_ScaleMode logical_scale_mode;
2550

2551
    /* Video */
2552

2553
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
2554
    SDLTest_DrawString(renderer, 0.0f, textY, "-- Video --");
2555
    textY += lineHeight;
2556

2557
    SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255);
2558

2559
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetCurrentVideoDriver: %s", SDL_GetCurrentVideoDriver());
2560
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2561
    textY += lineHeight;
2562

2563
    /* Renderer */
2564

2565
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
2566
    SDLTest_DrawString(renderer, 0.0f, textY, "-- Renderer --");
2567
    textY += lineHeight;
2568

2569
    SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255);
2570

2571
    name = SDL_GetRendererName(renderer);
2572
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetRendererName: %s", name);
2573
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2574
    textY += lineHeight;
2575

2576
    if (SDL_GetRenderOutputSize(renderer, &w, &h)) {
2577
        (void)SDL_snprintf(text, sizeof(text), "SDL_GetRenderOutputSize: %dx%d", w, h);
2578
        SDLTest_DrawString(renderer, 0.0f, textY, text);
2579
        textY += lineHeight;
2580
    }
2581

2582
    if (SDL_GetCurrentRenderOutputSize(renderer, &w, &h)) {
2583
        (void)SDL_snprintf(text, sizeof(text), "SDL_GetCurrentRenderOutputSize: %dx%d", w, h);
2584
        SDLTest_DrawString(renderer, 0.0f, textY, text);
2585
        textY += lineHeight;
2586
    }
2587

2588
    SDL_GetRenderViewport(renderer, &rect);
2589
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetRenderViewport: %d,%d, %dx%d",
2590
                       rect.x, rect.y, rect.w, rect.h);
2591
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2592
    textY += lineHeight;
2593

2594
    SDL_GetRenderScale(renderer, &scaleX, &scaleY);
2595
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetRenderScale: %g,%g",
2596
                       scaleX, scaleY);
2597
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2598
    textY += lineHeight;
2599

2600
    SDL_GetRenderLogicalPresentation(renderer, &w, &h, &logical_presentation, &logical_scale_mode);
2601
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetRenderLogicalPresentation: %dx%d ", w, h);
2602
    SDLTest_PrintLogicalPresentation(text, sizeof(text), logical_presentation);
2603
    SDL_snprintfcat(text, sizeof(text), ", ");
2604
    SDLTest_PrintScaleMode(text, sizeof(text), logical_scale_mode);
2605
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2606
    textY += lineHeight;
2607

2608
    /* Window */
2609

2610
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
2611
    SDLTest_DrawString(renderer, 0.0f, textY, "-- Window --");
2612
    textY += lineHeight;
2613

2614
    SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255);
2615

2616
    SDL_GetWindowPosition(window, &x, &y);
2617
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetWindowPosition: %d,%d", x, y);
2618
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2619
    textY += lineHeight;
2620

2621
    SDL_GetWindowSize(window, &w, &h);
2622
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetWindowSize: %dx%d", w, h);
2623
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2624
    textY += lineHeight;
2625

2626
    SDL_GetWindowSafeArea(window, &rect);
2627
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetWindowSafeArea: %d,%d %dx%d", rect.x, rect.y, rect.w, rect.h);
2628
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2629
    textY += lineHeight;
2630

2631
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetWindowFlags: ");
2632
    SDLTest_PrintWindowFlags(text, sizeof(text), SDL_GetWindowFlags(window));
2633
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2634
    textY += lineHeight;
2635

2636
    mode = SDL_GetWindowFullscreenMode(window);
2637
    if (mode) {
2638
        (void)SDL_snprintf(text, sizeof(text), "SDL_GetWindowFullscreenMode: %dx%d@%gx %gHz, (%s)",
2639
                           mode->w, mode->h, mode->pixel_density, mode->refresh_rate, SDL_GetPixelFormatName(mode->format));
2640
        SDLTest_DrawString(renderer, 0.0f, textY, text);
2641
        textY += lineHeight;
2642
    }
2643

2644
    /* Display */
2645

2646
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
2647
    SDLTest_DrawString(renderer, 0.0f, textY, "-- Display --");
2648
    textY += lineHeight;
2649

2650
    SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255);
2651

2652
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetDisplayForWindow: %" SDL_PRIu32, windowDisplayID);
2653
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2654
    textY += lineHeight;
2655

2656
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetDisplayName: %s", SDL_GetDisplayName(windowDisplayID));
2657
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2658
    textY += lineHeight;
2659

2660
    if (SDL_GetDisplayBounds(windowDisplayID, &rect)) {
2661
        (void)SDL_snprintf(text, sizeof(text), "SDL_GetDisplayBounds: %d,%d, %dx%d",
2662
                           rect.x, rect.y, rect.w, rect.h);
2663
        SDLTest_DrawString(renderer, 0.0f, textY, text);
2664
        textY += lineHeight;
2665
    }
2666

2667
    mode = SDL_GetCurrentDisplayMode(windowDisplayID);
2668
    if (mode) {
2669
        (void)SDL_snprintf(text, sizeof(text), "SDL_GetCurrentDisplayMode: %dx%d@%gx %gHz, (%s)",
2670
                           mode->w, mode->h, mode->pixel_density, mode->refresh_rate, SDL_GetPixelFormatName(mode->format));
2671
        SDLTest_DrawString(renderer, 0.0f, textY, text);
2672
        textY += lineHeight;
2673
    }
2674

2675
    mode = SDL_GetDesktopDisplayMode(windowDisplayID);
2676
    if (mode) {
2677
        (void)SDL_snprintf(text, sizeof(text), "SDL_GetDesktopDisplayMode: %dx%d@%gx %gHz, (%s)",
2678
                           mode->w, mode->h, mode->pixel_density, mode->refresh_rate, SDL_GetPixelFormatName(mode->format));
2679
        SDLTest_DrawString(renderer, 0.0f, textY, text);
2680
        textY += lineHeight;
2681
    }
2682

2683
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetNaturalDisplayOrientation: ");
2684
    SDLTest_PrintDisplayOrientation(text, sizeof(text), SDL_GetNaturalDisplayOrientation(windowDisplayID));
2685
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2686
    textY += lineHeight;
2687

2688
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetCurrentDisplayOrientation: ");
2689
    SDLTest_PrintDisplayOrientation(text, sizeof(text), SDL_GetCurrentDisplayOrientation(windowDisplayID));
2690
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2691
    textY += lineHeight;
2692

2693
    /* Mouse */
2694

2695
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
2696
    SDLTest_DrawString(renderer, 0.0f, textY, "-- Mouse --");
2697
    textY += lineHeight;
2698

2699
    SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255);
2700

2701
    flags = SDL_GetMouseState(&fx, &fy);
2702
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetMouseState: %g,%g ", fx, fy);
2703
    SDLTest_PrintButtonMask(text, sizeof(text), flags);
2704
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2705
    textY += lineHeight;
2706

2707
    flags = SDL_GetGlobalMouseState(&fx, &fy);
2708
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetGlobalMouseState: %g,%g ", fx, fy);
2709
    SDLTest_PrintButtonMask(text, sizeof(text), flags);
2710
    SDLTest_DrawString(renderer, 0.0f, textY, text);
2711
    textY += lineHeight;
2712

2713
    /* Keyboard */
2714

2715
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
2716
    SDLTest_DrawString(renderer, 0, textY, "-- Keyboard --");
2717
    textY += lineHeight;
2718

2719
    SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255);
2720

2721
    (void)SDL_snprintf(text, sizeof(text), "SDL_GetModState: ");
2722
    SDLTest_PrintModState(text, sizeof(text), SDL_GetModState());
2723
    SDLTest_DrawString(renderer, 0, textY, text);
2724
    textY += lineHeight;
2725

2726
    if (usedHeight) {
2727
        *usedHeight = textY;
2728
    }
2729
}
2730

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.