diff options
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/testcustomcursor.c')
-rw-r--r-- | src/contrib/SDL-3.2.20/test/testcustomcursor.c | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/test/testcustomcursor.c b/src/contrib/SDL-3.2.20/test/testcustomcursor.c new file mode 100644 index 0000000..5472291 --- /dev/null +++ b/src/contrib/SDL-3.2.20/test/testcustomcursor.c | |||
@@ -0,0 +1,470 @@ | |||
1 | /* | ||
2 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
3 | |||
4 | This software is provided 'as-is', without any express or implied | ||
5 | warranty. In no event will the authors be held liable for any damages | ||
6 | arising from the use of this software. | ||
7 | |||
8 | Permission is granted to anyone to use this software for any purpose, | ||
9 | including commercial applications, and to alter it and redistribute it | ||
10 | freely. | ||
11 | */ | ||
12 | |||
13 | #include <SDL3/SDL_test_common.h> | ||
14 | #include <SDL3/SDL_main.h> | ||
15 | |||
16 | #ifdef SDL_PLATFORM_EMSCRIPTEN | ||
17 | #include <emscripten/emscripten.h> | ||
18 | #endif | ||
19 | |||
20 | #include <stdlib.h> | ||
21 | |||
22 | /* Stolen from the mailing list */ | ||
23 | /* Creates a new mouse cursor from an XPM */ | ||
24 | |||
25 | /* XPM */ | ||
26 | static const char *arrow[] = { | ||
27 | /* width height num_colors chars_per_pixel */ | ||
28 | " 32 32 3 1", | ||
29 | /* colors */ | ||
30 | "X c #000000", | ||
31 | ". c #ffffff", | ||
32 | " c None", | ||
33 | /* pixels */ | ||
34 | "X ", | ||
35 | "XX ", | ||
36 | "X.X ", | ||
37 | "X..X ", | ||
38 | "X...X ", | ||
39 | "X....X ", | ||
40 | "X.....X ", | ||
41 | "X......X ", | ||
42 | "X.......X ", | ||
43 | "X........X ", | ||
44 | "X.....XXXXX ", | ||
45 | "X..X..X ", | ||
46 | "X.X X..X ", | ||
47 | "XX X..X ", | ||
48 | "X X..X ", | ||
49 | " X..X ", | ||
50 | " X..X ", | ||
51 | " X..X ", | ||
52 | " XX ", | ||
53 | " ", | ||
54 | " ", | ||
55 | " ", | ||
56 | " ", | ||
57 | " ", | ||
58 | " ", | ||
59 | " ", | ||
60 | " ", | ||
61 | " ", | ||
62 | " ", | ||
63 | " ", | ||
64 | " ", | ||
65 | " ", | ||
66 | "0,0" | ||
67 | }; | ||
68 | |||
69 | static const char *cross[] = { | ||
70 | /* width height num_colors chars_per_pixel */ | ||
71 | " 32 32 3 1", | ||
72 | /* colors */ | ||
73 | "o c #000000", | ||
74 | ". c #ffffff", | ||
75 | " c None", | ||
76 | /* pixels */ | ||
77 | " ", | ||
78 | " ", | ||
79 | " ", | ||
80 | " ", | ||
81 | " oo ", | ||
82 | " oo ", | ||
83 | " oo ", | ||
84 | " oo ", | ||
85 | " oo ", | ||
86 | " oo ", | ||
87 | " oo ", | ||
88 | " oo ", | ||
89 | " oo ", | ||
90 | " oo ", | ||
91 | " oo ", | ||
92 | " oooooooooooooooooooooooo ", | ||
93 | " oooooooooooooooooooooooo ", | ||
94 | " oo ", | ||
95 | " oo ", | ||
96 | " oo ", | ||
97 | " oo ", | ||
98 | " oo ", | ||
99 | " oo ", | ||
100 | " oo ", | ||
101 | " oo ", | ||
102 | " oo ", | ||
103 | " oo ", | ||
104 | " oo ", | ||
105 | " ", | ||
106 | " ", | ||
107 | " ", | ||
108 | " ", | ||
109 | "0,0" | ||
110 | }; | ||
111 | |||
112 | static SDL_Surface *load_image_file(const char *file) | ||
113 | { | ||
114 | SDL_Surface *surface = SDL_LoadBMP(file); | ||
115 | if (surface) { | ||
116 | if (SDL_GetSurfacePalette(surface)) { | ||
117 | const Uint8 bpp = SDL_BITSPERPIXEL(surface->format); | ||
118 | const Uint8 mask = (1 << bpp) - 1; | ||
119 | if (SDL_PIXELORDER(surface->format) == SDL_BITMAPORDER_4321) | ||
120 | SDL_SetSurfaceColorKey(surface, 1, (*(Uint8 *)surface->pixels) & mask); | ||
121 | else | ||
122 | SDL_SetSurfaceColorKey(surface, 1, ((*(Uint8 *)surface->pixels) >> (8 - bpp)) & mask); | ||
123 | } else { | ||
124 | switch (SDL_BITSPERPIXEL(surface->format)) { | ||
125 | case 15: | ||
126 | SDL_SetSurfaceColorKey(surface, 1, (*(Uint16 *)surface->pixels) & 0x00007FFF); | ||
127 | break; | ||
128 | case 16: | ||
129 | SDL_SetSurfaceColorKey(surface, 1, *(Uint16 *)surface->pixels); | ||
130 | break; | ||
131 | case 24: | ||
132 | SDL_SetSurfaceColorKey(surface, 1, (*(Uint32 *)surface->pixels) & 0x00FFFFFF); | ||
133 | break; | ||
134 | case 32: | ||
135 | SDL_SetSurfaceColorKey(surface, 1, *(Uint32 *)surface->pixels); | ||
136 | break; | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | return surface; | ||
141 | } | ||
142 | |||
143 | static SDL_Surface *load_image(const char *file) | ||
144 | { | ||
145 | SDL_Surface *surface = load_image_file(file); | ||
146 | if (surface) { | ||
147 | /* Add a 2x version of this image, if available */ | ||
148 | SDL_Surface *surface2x = NULL; | ||
149 | const char *ext = SDL_strrchr(file, '.'); | ||
150 | size_t len = SDL_strlen(file) + 2 + 1; | ||
151 | char *file2x = (char *)SDL_malloc(len); | ||
152 | if (file2x) { | ||
153 | SDL_strlcpy(file2x, file, len); | ||
154 | if (ext) { | ||
155 | SDL_memcpy(file2x + (ext - file), "2x", 3); | ||
156 | SDL_strlcat(file2x, ext, len); | ||
157 | } else { | ||
158 | SDL_strlcat(file2x, "2x", len); | ||
159 | } | ||
160 | surface2x = load_image_file(file2x); | ||
161 | SDL_free(file2x); | ||
162 | } | ||
163 | if (surface2x) { | ||
164 | SDL_AddSurfaceAlternateImage(surface, surface2x); | ||
165 | SDL_DestroySurface(surface2x); | ||
166 | } | ||
167 | } | ||
168 | return surface; | ||
169 | } | ||
170 | |||
171 | static SDL_Cursor *init_color_cursor(const char *file) | ||
172 | { | ||
173 | SDL_Cursor *cursor = NULL; | ||
174 | SDL_Surface *surface = load_image(file); | ||
175 | if (surface) { | ||
176 | cursor = SDL_CreateColorCursor(surface, 0, 0); | ||
177 | SDL_DestroySurface(surface); | ||
178 | } | ||
179 | return cursor; | ||
180 | } | ||
181 | |||
182 | static SDL_Cursor *init_system_cursor(const char *image[]) | ||
183 | { | ||
184 | int i, row, col; | ||
185 | Uint8 data[4 * 32]; | ||
186 | Uint8 mask[4 * 32]; | ||
187 | int hot_x = 0; | ||
188 | int hot_y = 0; | ||
189 | |||
190 | i = -1; | ||
191 | for (row = 0; row < 32; ++row) { | ||
192 | for (col = 0; col < 32; ++col) { | ||
193 | if (col % 8) { | ||
194 | data[i] <<= 1; | ||
195 | mask[i] <<= 1; | ||
196 | } else { | ||
197 | ++i; | ||
198 | data[i] = mask[i] = 0; | ||
199 | } | ||
200 | switch (image[4 + row][col]) { | ||
201 | case 'X': | ||
202 | data[i] |= 0x01; | ||
203 | mask[i] |= 0x01; | ||
204 | break; | ||
205 | case '.': | ||
206 | mask[i] |= 0x01; | ||
207 | break; | ||
208 | case 'o': | ||
209 | data[i] |= 0x01; | ||
210 | break; | ||
211 | case ' ': | ||
212 | break; | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | (void)SDL_sscanf(image[4 + row], "%d,%d", &hot_x, &hot_y); | ||
217 | return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y); | ||
218 | } | ||
219 | |||
220 | static SDLTest_CommonState *state; | ||
221 | static int done; | ||
222 | static SDL_Cursor *cursors[3 + SDL_SYSTEM_CURSOR_COUNT]; | ||
223 | static SDL_SystemCursor cursor_types[3 + SDL_SYSTEM_CURSOR_COUNT]; | ||
224 | static int num_cursors; | ||
225 | static int current_cursor; | ||
226 | static bool show_cursor; | ||
227 | |||
228 | /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ | ||
229 | static void | ||
230 | quit(int rc) | ||
231 | { | ||
232 | SDLTest_CommonQuit(state); | ||
233 | /* Let 'main()' return normally */ | ||
234 | if (rc != 0) { | ||
235 | exit(rc); | ||
236 | } | ||
237 | } | ||
238 | |||
239 | static void loop(void) | ||
240 | { | ||
241 | int i; | ||
242 | SDL_Event event; | ||
243 | /* Check for events */ | ||
244 | while (SDL_PollEvent(&event)) { | ||
245 | SDLTest_CommonEvent(state, &event, &done); | ||
246 | if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { | ||
247 | if (event.button.button == SDL_BUTTON_LEFT) { | ||
248 | if (num_cursors == 0) { | ||
249 | continue; | ||
250 | } | ||
251 | |||
252 | ++current_cursor; | ||
253 | if (current_cursor == num_cursors) { | ||
254 | current_cursor = 0; | ||
255 | } | ||
256 | |||
257 | SDL_SetCursor(cursors[current_cursor]); | ||
258 | |||
259 | switch ((int)cursor_types[current_cursor]) { | ||
260 | case (SDL_SystemCursor)-1: | ||
261 | SDL_Log("Custom cursor"); | ||
262 | break; | ||
263 | case SDL_SYSTEM_CURSOR_DEFAULT: | ||
264 | SDL_Log("Default"); | ||
265 | break; | ||
266 | case SDL_SYSTEM_CURSOR_TEXT: | ||
267 | SDL_Log("Text"); | ||
268 | break; | ||
269 | case SDL_SYSTEM_CURSOR_WAIT: | ||
270 | SDL_Log("Wait"); | ||
271 | break; | ||
272 | case SDL_SYSTEM_CURSOR_CROSSHAIR: | ||
273 | SDL_Log("Crosshair"); | ||
274 | break; | ||
275 | case SDL_SYSTEM_CURSOR_PROGRESS: | ||
276 | SDL_Log("Progress: Small wait cursor (or Wait if not available)"); | ||
277 | break; | ||
278 | case SDL_SYSTEM_CURSOR_NWSE_RESIZE: | ||
279 | SDL_Log("Double arrow pointing northwest and southeast"); | ||
280 | break; | ||
281 | case SDL_SYSTEM_CURSOR_NESW_RESIZE: | ||
282 | SDL_Log("Double arrow pointing northeast and southwest"); | ||
283 | break; | ||
284 | case SDL_SYSTEM_CURSOR_EW_RESIZE: | ||
285 | SDL_Log("Double arrow pointing west and east"); | ||
286 | break; | ||
287 | case SDL_SYSTEM_CURSOR_NS_RESIZE: | ||
288 | SDL_Log("Double arrow pointing north and south"); | ||
289 | break; | ||
290 | case SDL_SYSTEM_CURSOR_MOVE: | ||
291 | SDL_Log("Move: Four pointed arrow pointing north, south, east, and west"); | ||
292 | break; | ||
293 | case SDL_SYSTEM_CURSOR_NOT_ALLOWED: | ||
294 | SDL_Log("Not Allowed: Slashed circle or crossbones"); | ||
295 | break; | ||
296 | case SDL_SYSTEM_CURSOR_POINTER: | ||
297 | SDL_Log("Pointer: Hand"); | ||
298 | break; | ||
299 | case SDL_SYSTEM_CURSOR_NW_RESIZE: | ||
300 | SDL_Log("Window resize top-left"); | ||
301 | break; | ||
302 | case SDL_SYSTEM_CURSOR_N_RESIZE: | ||
303 | SDL_Log("Window resize top"); | ||
304 | break; | ||
305 | case SDL_SYSTEM_CURSOR_NE_RESIZE: | ||
306 | SDL_Log("Window resize top-right"); | ||
307 | break; | ||
308 | case SDL_SYSTEM_CURSOR_E_RESIZE: | ||
309 | SDL_Log("Window resize right"); | ||
310 | break; | ||
311 | case SDL_SYSTEM_CURSOR_SE_RESIZE: | ||
312 | SDL_Log("Window resize bottom-right"); | ||
313 | break; | ||
314 | case SDL_SYSTEM_CURSOR_S_RESIZE: | ||
315 | SDL_Log("Window resize bottom"); | ||
316 | break; | ||
317 | case SDL_SYSTEM_CURSOR_SW_RESIZE: | ||
318 | SDL_Log("Window resize bottom-left"); | ||
319 | break; | ||
320 | case SDL_SYSTEM_CURSOR_W_RESIZE: | ||
321 | SDL_Log("Window resize left"); | ||
322 | break; | ||
323 | default: | ||
324 | SDL_Log("UNKNOWN CURSOR TYPE, FIX THIS PROGRAM."); | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | } else { | ||
329 | show_cursor = !show_cursor; | ||
330 | if (show_cursor) { | ||
331 | SDL_ShowCursor(); | ||
332 | } else { | ||
333 | SDL_HideCursor(); | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | for (i = 0; i < state->num_windows; ++i) { | ||
340 | SDL_Renderer *renderer = state->renderers[i]; | ||
341 | SDL_FRect rect; | ||
342 | int x, y, row; | ||
343 | int window_w = 0, window_h = 0; | ||
344 | const float scale = SDL_GetWindowPixelDensity(state->windows[i]); | ||
345 | |||
346 | SDL_GetWindowSizeInPixels(state->windows[i], &window_w, &window_h); | ||
347 | rect.w = 128.0f * scale; | ||
348 | rect.h = 128.0f * scale; | ||
349 | for (y = 0, row = 0; y < window_h; y += (int)rect.h, ++row) { | ||
350 | bool black = ((row % 2) == 0) ? true : false; | ||
351 | for (x = 0; x < window_w; x += (int)rect.w) { | ||
352 | rect.x = (float)x; | ||
353 | rect.y = (float)y; | ||
354 | |||
355 | if (black) { | ||
356 | SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); | ||
357 | } else { | ||
358 | SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); | ||
359 | } | ||
360 | SDL_RenderFillRect(renderer, &rect); | ||
361 | |||
362 | black = !black; | ||
363 | } | ||
364 | } | ||
365 | SDL_RenderPresent(renderer); | ||
366 | } | ||
367 | #ifdef SDL_PLATFORM_EMSCRIPTEN | ||
368 | if (done) { | ||
369 | emscripten_cancel_main_loop(); | ||
370 | } | ||
371 | #endif | ||
372 | } | ||
373 | |||
374 | int main(int argc, char *argv[]) | ||
375 | { | ||
376 | int i; | ||
377 | const char *color_cursor = NULL; | ||
378 | SDL_Cursor *cursor; | ||
379 | |||
380 | /* Initialize test framework */ | ||
381 | state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); | ||
382 | if (!state) { | ||
383 | return 1; | ||
384 | } | ||
385 | |||
386 | for (i = 1; i < argc;) { | ||
387 | int consumed; | ||
388 | |||
389 | consumed = SDLTest_CommonArg(state, i); | ||
390 | if (consumed == 0) { | ||
391 | color_cursor = argv[i]; | ||
392 | break; | ||
393 | } | ||
394 | if (consumed < 0) { | ||
395 | SDLTest_CommonLogUsage(state, argv[0], NULL); | ||
396 | quit(1); | ||
397 | } | ||
398 | i += consumed; | ||
399 | } | ||
400 | |||
401 | if (!SDLTest_CommonInit(state)) { | ||
402 | quit(2); | ||
403 | } | ||
404 | |||
405 | num_cursors = 0; | ||
406 | |||
407 | if (color_cursor) { | ||
408 | SDL_Surface *icon = load_image(color_cursor); | ||
409 | if (icon) { | ||
410 | for (i = 0; i < state->num_windows; ++i) { | ||
411 | SDL_SetWindowIcon(state->windows[i], icon); | ||
412 | } | ||
413 | SDL_DestroySurface(icon); | ||
414 | } | ||
415 | |||
416 | cursor = init_color_cursor(color_cursor); | ||
417 | if (cursor) { | ||
418 | cursors[num_cursors] = cursor; | ||
419 | cursor_types[num_cursors] = (SDL_SystemCursor)-1; | ||
420 | num_cursors++; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | cursor = init_system_cursor(arrow); | ||
425 | if (cursor) { | ||
426 | cursors[num_cursors] = cursor; | ||
427 | cursor_types[num_cursors] = (SDL_SystemCursor)-1; | ||
428 | num_cursors++; | ||
429 | } | ||
430 | |||
431 | cursor = init_system_cursor(cross); | ||
432 | if (cursor) { | ||
433 | cursors[num_cursors] = cursor; | ||
434 | cursor_types[num_cursors] = (SDL_SystemCursor)-1; | ||
435 | num_cursors++; | ||
436 | } | ||
437 | |||
438 | for (i = 0; i < SDL_SYSTEM_CURSOR_COUNT; ++i) { | ||
439 | cursor = SDL_CreateSystemCursor((SDL_SystemCursor)i); | ||
440 | if (cursor) { | ||
441 | cursors[num_cursors] = cursor; | ||
442 | cursor_types[num_cursors] = i; | ||
443 | num_cursors++; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | if (num_cursors > 0) { | ||
448 | SDL_SetCursor(cursors[0]); | ||
449 | } | ||
450 | |||
451 | show_cursor = SDL_CursorVisible(); | ||
452 | |||
453 | /* Main render loop */ | ||
454 | done = 0; | ||
455 | #ifdef SDL_PLATFORM_EMSCRIPTEN | ||
456 | emscripten_set_main_loop(loop, 0, 1); | ||
457 | #else | ||
458 | while (!done) { | ||
459 | loop(); | ||
460 | } | ||
461 | #endif | ||
462 | |||
463 | for (i = 0; i < num_cursors; ++i) { | ||
464 | SDL_DestroyCursor(cursors[i]); | ||
465 | } | ||
466 | quit(0); | ||
467 | |||
468 | /* keep the compiler happy ... */ | ||
469 | return 0; | ||
470 | } | ||