1 /*
2   Copyright (C) 1997-2021 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 <stdlib.h>
14 #include <stdio.h>
15 
16 #ifdef __EMSCRIPTEN__
17 #include <emscripten/emscripten.h>
18 #endif
19 
20 #include "SDL_test_common.h"
21 #include "SDL_test_font.h"
22 
23 static SDLTest_CommonState *state;
24 int done;
25 
26 static const char *cursorNames[] = {
27         "arrow",
28         "ibeam",
29         "wait",
30         "crosshair",
31         "waitarrow",
32         "sizeNWSE",
33         "sizeNESW",
34         "sizeWE",
35         "sizeNS",
36         "sizeALL",
37         "NO",
38         "hand",
39 };
40 int system_cursor = -1;
41 SDL_Cursor *cursor = NULL;
42 SDL_bool relative_mode = SDL_FALSE;
43 int highlighted_mode = -1;
44 
45 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
46 static void
quit(int rc)47 quit(int rc)
48 {
49     SDLTest_CommonQuit(state);
50     exit(rc);
51 }
52 
53 /* Draws the modes menu, and stores the mode index under the mouse in highlighted_mode */
54 static void
draw_modes_menu(SDL_Window * window,SDL_Renderer * renderer,SDL_Rect viewport)55 draw_modes_menu(SDL_Window *window, SDL_Renderer *renderer, SDL_Rect viewport)
56 {
57     SDL_DisplayMode mode;
58     char text[1024];
59     const int lineHeight = 10;
60     const int display_index = SDL_GetWindowDisplayIndex(window);
61     const int num_modes = SDL_GetNumDisplayModes(display_index);
62     int i;
63     int column_chars = 0;
64     int text_length;
65     int x, y;
66     int table_top;
67     SDL_Point mouse_pos = { -1, -1 };
68 
69     /* Get mouse position */
70     if (SDL_GetMouseFocus() == window) {
71         int window_x, window_y;
72         float logical_x, logical_y;
73 
74         SDL_GetMouseState(&window_x, &window_y);
75         SDL_RenderWindowToLogical(renderer, window_x, window_y, &logical_x, &logical_y);
76 
77         mouse_pos.x = (int)logical_x;
78         mouse_pos.y = (int)logical_y;
79     }
80 
81     x = 0;
82     y = viewport.y;
83 
84     y += lineHeight;
85 
86     SDL_snprintf(text, sizeof(text), "Click on a mode to set it with SDL_SetWindowDisplayMode");
87     SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
88     SDLTest_DrawString(renderer, x, y, text);
89     y += lineHeight;
90 
91     SDL_snprintf(text, sizeof(text), "Press Ctrl+Enter to toggle SDL_WINDOW_FULLSCREEN");
92     SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
93     SDLTest_DrawString(renderer, x, y, text);
94     y += lineHeight;
95 
96     table_top = y;
97 
98     /* Clear the cached mode under the mouse */
99     if (window == SDL_GetMouseFocus()) {
100         highlighted_mode = -1;
101     }
102 
103     for (i = 0; i < num_modes; ++i) {
104         SDL_Rect cell_rect;
105 
106         if (0 != SDL_GetDisplayMode(display_index, i, &mode)) {
107             return;
108         }
109 
110         SDL_snprintf(text, sizeof(text), "%d: %dx%d@%dHz",
111             i, mode.w, mode.h, mode.refresh_rate);
112 
113         /* Update column width */
114         text_length = (int)SDL_strlen(text);
115         column_chars = SDL_max(column_chars, text_length);
116 
117         /* Check if under mouse */
118         cell_rect.x = x;
119         cell_rect.y = y;
120         cell_rect.w = text_length * FONT_CHARACTER_SIZE;
121         cell_rect.h = lineHeight;
122 
123         if (SDL_PointInRect(&mouse_pos, &cell_rect)) {
124             SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
125 
126             /* Update cached mode under the mouse */
127             if (window == SDL_GetMouseFocus()) {
128                 highlighted_mode = i;
129             }
130         } else {
131             SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255);
132         }
133 
134         SDLTest_DrawString(renderer, x, y, text);
135         y += lineHeight;
136 
137         if (y + lineHeight > (viewport.y + viewport.h)) {
138             /* Advance to next column */
139             x += (column_chars + 1) * FONT_CHARACTER_SIZE;
140             y = table_top;
141             column_chars = 0;
142         }
143     }
144 }
145 
146 void
loop()147 loop()
148 {
149     int i;
150     SDL_Event event;
151         /* Check for events */
152         while (SDL_PollEvent(&event)) {
153             SDLTest_CommonEvent(state, &event, &done);
154 
155             if (event.type == SDL_WINDOWEVENT) {
156                 if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
157                     SDL_Window *window = SDL_GetWindowFromID(event.window.windowID);
158                     if (window) {
159                         SDL_Log("Window %d resized to %dx%d\n",
160                             event.window.windowID,
161                             event.window.data1,
162                             event.window.data2);
163                     }
164                 }
165                 if (event.window.event == SDL_WINDOWEVENT_MOVED) {
166                     SDL_Window *window = SDL_GetWindowFromID(event.window.windowID);
167                     if (window) {
168                         SDL_Log("Window %d moved to %d,%d (display %s)\n",
169                             event.window.windowID,
170                             event.window.data1,
171                             event.window.data2,
172                             SDL_GetDisplayName(SDL_GetWindowDisplayIndex(window)));
173                     }
174                 }
175                 if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) {
176                     relative_mode = SDL_GetRelativeMouseMode();
177                     if (relative_mode) {
178                         SDL_SetRelativeMouseMode(SDL_FALSE);
179                     }
180                 }
181                 if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
182                     if (relative_mode) {
183                         SDL_SetRelativeMouseMode(SDL_TRUE);
184                     }
185                 }
186             }
187             if (event.type == SDL_KEYUP) {
188                 SDL_bool updateCursor = SDL_FALSE;
189 
190                 if (event.key.keysym.sym == SDLK_LEFT) {
191                     --system_cursor;
192                     if (system_cursor < 0) {
193                         system_cursor = SDL_NUM_SYSTEM_CURSORS - 1;
194                     }
195                     updateCursor = SDL_TRUE;
196                 } else if (event.key.keysym.sym == SDLK_RIGHT) {
197                     ++system_cursor;
198                     if (system_cursor >= SDL_NUM_SYSTEM_CURSORS) {
199                         system_cursor = 0;
200                     }
201                     updateCursor = SDL_TRUE;
202                 }
203                 if (updateCursor) {
204                     SDL_Log("Changing cursor to \"%s\"", cursorNames[system_cursor]);
205                     SDL_FreeCursor(cursor);
206                     cursor = SDL_CreateSystemCursor((SDL_SystemCursor)system_cursor);
207                     SDL_SetCursor(cursor);
208                 }
209             }
210             if (event.type == SDL_MOUSEBUTTONUP) {
211                 SDL_Window* window = SDL_GetMouseFocus();
212                 if (highlighted_mode != -1 && window != NULL) {
213                     const int display_index = SDL_GetWindowDisplayIndex(window);
214                     SDL_DisplayMode mode;
215                     if (0 != SDL_GetDisplayMode(display_index, highlighted_mode, &mode)) {
216                         SDL_Log("Couldn't get display mode");
217                     } else {
218                         SDL_SetWindowDisplayMode(window, &mode);
219                     }
220                 }
221             }
222         }
223 
224         for (i = 0; i < state->num_windows; ++i) {
225             SDL_Window* window = state->windows[i];
226             SDL_Renderer *renderer = state->renderers[i];
227             if (window != NULL && renderer != NULL) {
228                 int y = 0;
229                 SDL_Rect viewport, menurect;
230 
231                 SDL_RenderGetViewport(renderer, &viewport);
232 
233                 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
234                 SDL_RenderClear(renderer);
235 
236                 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
237                 SDLTest_CommonDrawWindowInfo(renderer, state->windows[i], &y);
238 
239                 menurect.x = 0;
240                 menurect.y = y;
241                 menurect.w = viewport.w;
242                 menurect.h = viewport.h - y;
243                 draw_modes_menu(window, renderer, menurect);
244 
245                 SDL_RenderPresent(renderer);
246             }
247         }
248 #ifdef __EMSCRIPTEN__
249     if (done) {
250         emscripten_cancel_main_loop();
251     }
252 #endif
253 }
254 
255 int
main(int argc,char * argv[])256 main(int argc, char *argv[])
257 {
258     int i;
259 
260     /* Enable standard application logging */
261     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
262 
263     SDL_assert(SDL_arraysize(cursorNames) == SDL_NUM_SYSTEM_CURSORS);
264 
265     /* Initialize test framework */
266     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
267     if (!state) {
268         return 1;
269     }
270 
271     if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) {
272         SDLTest_CommonQuit(state);
273         return 1;
274     }
275 
276     SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
277     SDL_EventState(SDL_DROPTEXT, SDL_ENABLE);
278 
279     for (i = 0; i < state->num_windows; ++i) {
280         SDL_Renderer *renderer = state->renderers[i];
281         SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
282         SDL_RenderClear(renderer);
283     }
284 
285     /* Main render loop */
286     done = 0;
287 #ifdef __EMSCRIPTEN__
288     emscripten_set_main_loop(loop, 0, 1);
289 #else
290     while (!done) {
291         loop();
292     }
293 #endif
294     SDL_FreeCursor(cursor);
295 
296     quit(0);
297     /* keep the compiler happy ... */
298     return(0);
299 }
300 
301 /* vi: set ts=4 sw=4 expandtab: */
302