Atlas - testpopup.c

Home / ext / SDL / test Lines: 1 | Size: 9074 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 3 4This software is provided 'as-is', without any express or implied 5warranty. In no event will the authors be held liable for any damages 6arising from the use of this software. 7 8Permission is granted to anyone to use this software for any purpose, 9including commercial applications, and to alter it and redistribute it 10freely. 11*/ 12/* Simple program: Move N sprites around on the screen as fast as possible */ 13 14#include <SDL3/SDL_main.h> 15#include <SDL3/SDL_test_common.h> 16#include <SDL3/SDL_test_font.h> 17 18#ifdef SDL_PLATFORM_EMSCRIPTEN 19#include <emscripten/emscripten.h> 20#endif 21 22#include <stdlib.h> 23 24#define MENU_WIDTH 120 25#define MENU_HEIGHT 300 26 27#define TOOLTIP_DELAY 500 28#define TOOLTIP_WIDTH 175 29#define TOOLTIP_HEIGHT 32 30 31static SDLTest_CommonState *state; 32static int num_menus; 33static Uint64 tooltip_timer; 34static int done; 35static const SDL_Color colors[] = { 36 { 0x7F, 0x00, 0x00, 0xFF }, 37 { 0x00, 0x7F, 0x00, 0xFF }, 38 { 0x00, 0x00, 0x7F, 0xFF } 39}; 40 41struct PopupWindow 42{ 43 SDL_Window *win; 44 SDL_Window *parent; 45 SDL_Renderer *renderer; 46 int idx; 47}; 48 49static struct PopupWindow *menus; 50static struct PopupWindow tooltip; 51 52static bool no_constraints; 53static bool no_grab; 54 55/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ 56static void quit(int rc) 57{ 58 SDL_free(menus); 59 menus = NULL; 60 61 SDLTest_CleanupTextDrawing(); 62 SDLTest_CommonQuit(state); 63 /* Let 'main()' return normally */ 64 if (rc != 0) { 65 exit(rc); 66 } 67} 68 69static int get_menu_index_by_window(SDL_Window *window) 70{ 71 int i; 72 for (i = 0; i < num_menus; ++i) { 73 if (menus[i].win == window) { 74 return i; 75 } 76 } 77 78 return -1; 79} 80 81static bool window_is_root(SDL_Window *window) 82{ 83 int i; 84 for (i = 0; i < state->num_windows; ++i) { 85 if (window == state->windows[i]) { 86 return true; 87 } 88 } 89 90 return false; 91} 92 93static bool create_popup(struct PopupWindow *new_popup, bool is_menu) 94{ 95 SDL_Window *focus; 96 SDL_Window *new_win; 97 SDL_Renderer *new_renderer; 98 const int w = is_menu ? MENU_WIDTH : TOOLTIP_WIDTH; 99 const int h = is_menu ? MENU_HEIGHT : TOOLTIP_HEIGHT; 100 const int v_off = is_menu ? 0 : 32; 101 float x, y; 102 103 focus = SDL_GetMouseFocus(); 104 105 SDL_GetMouseState(&x, &y); 106 107 SDL_PropertiesID props = SDL_CreateProperties(); 108 SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, focus); 109 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN, !no_constraints); 110 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, !no_grab); 111 if (is_menu) { 112 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN, true); 113 } else { 114 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN, true); 115 } 116 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, w); 117 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, h); 118 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, (int)x); 119 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, (int)y + v_off); 120 new_win = SDL_CreateWindowWithProperties(props); 121 SDL_DestroyProperties(props); 122 123 if (new_win) { 124 new_renderer = SDL_CreateRenderer(new_win, state->renderdriver); 125 126 new_popup->win = new_win; 127 new_popup->renderer = new_renderer; 128 new_popup->parent = focus; 129 130 return true; 131 } 132 133 SDL_zerop(new_popup); 134 return false; 135} 136 137static void close_popups(void) 138{ 139 int i; 140 141 for (i = 0; i < num_menus; ++i) { 142 /* Destroying the lowest level window recursively destroys the child windows */ 143 if (window_is_root(menus[i].parent)) { 144 SDL_DestroyWindow(menus[i].win); 145 } 146 } 147 SDL_free(menus); 148 menus = NULL; 149 num_menus = 0; 150 151 /* If the tooltip was a child of a popup, it was recursively destroyed with the popup */ 152 if (!window_is_root(tooltip.parent)) { 153 SDL_zero(tooltip); 154 } 155} 156 157static void loop(void) 158{ 159 int i; 160 char fmt_str[128]; 161 SDL_Event event; 162 163 /* Check for events */ 164 while (SDL_PollEvent(&event)) { 165 if (event.type == SDL_EVENT_MOUSE_MOTION) { 166 /* Hide the tooltip and restart the timer if the mouse is moved */ 167 if (tooltip.win) { 168 SDL_DestroyWindow(tooltip.win); 169 SDL_zero(tooltip); 170 } 171 tooltip_timer = SDL_GetTicks() + TOOLTIP_DELAY; 172 173 if (num_menus > 0 && event.motion.windowID == SDL_GetWindowID(menus[0].parent)) { 174 int x = (int)event.motion.x; 175 int y = (int)event.motion.y; 176 177 SDL_SetWindowPosition(menus[0].win, x, y); 178 } 179 } else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { 180 /* Left click closes the popup menus */ 181 if (event.button.button == SDL_BUTTON_LEFT) { 182 close_popups(); 183 } else if (event.button.button == SDL_BUTTON_RIGHT) { 184 /* Create a new popup menu */ 185 menus = SDL_realloc(menus, sizeof(struct PopupWindow) * (num_menus + 1)); 186 if (create_popup(&menus[num_menus], true)) { 187 ++num_menus; 188 } 189 } 190 } else if (event.type == SDL_EVENT_KEY_DOWN) { 191 if (event.key.key == SDLK_SPACE) { 192 for (i = 0; i < num_menus; ++i) { 193 if (SDL_GetWindowFlags(menus[i].win) & SDL_WINDOW_HIDDEN) { 194 SDL_ShowWindow(menus[i].win); 195 } else { 196 SDL_HideWindow(menus[i].win); 197 } 198 } 199 /* Don't process this event in SDLTest_CommonEvent() */ 200 continue; 201 } 202 } 203 204 SDLTest_CommonEvent(state, &event, &done); 205 } 206 207 if (done) { 208 return; 209 } 210 211 /* Show the tooltip if the delay period has elapsed */ 212 if (SDL_GetTicks() > tooltip_timer) { 213 if (!tooltip.win) { 214 create_popup(&tooltip, false); 215 } 216 } 217 218 /* Draw the window */ 219 for (i = 0; i < state->num_windows; ++i) { 220 SDL_Renderer *renderer = state->renderers[i]; 221 SDL_RenderClear(renderer); 222 SDL_RenderPresent(renderer); 223 } 224 225 /* Draw the menus in alternating colors */ 226 for (i = 0; i < num_menus; ++i) { 227 const SDL_Color *c = &colors[i % SDL_arraysize(colors)]; 228 SDL_Renderer *renderer = menus[i].renderer; 229 230 SDL_SetRenderDrawColor(renderer, c->r, c->g, c->b, c->a); 231 SDL_RenderClear(renderer); 232 SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); 233 SDL_snprintf(fmt_str, sizeof(fmt_str), "Popup Menu %i", i); 234 SDLTest_DrawString(renderer, 10.0f, 10.0f, fmt_str); 235 SDL_RenderPresent(renderer); 236 } 237 238 /* Draw the tooltip */ 239 if (tooltip.win) { 240 int menu_idx; 241 242 SDL_SetRenderDrawColor(tooltip.renderer, 0x00, 0x00, 0x00, 0xFF); 243 SDL_RenderClear(tooltip.renderer); 244 SDL_SetRenderDrawColor(tooltip.renderer, 0xFF, 0xFF, 0xFF, 0xFF); 245 246 menu_idx = get_menu_index_by_window(tooltip.parent); 247 if (menu_idx >= 0) { 248 SDL_snprintf(fmt_str, sizeof(fmt_str), "Tooltip for popup %i", menu_idx); 249 } else { 250 SDL_snprintf(fmt_str, sizeof(fmt_str), "Toplevel tooltip"); 251 } 252 SDLTest_DrawString(tooltip.renderer, 10.0f, TOOLTIP_HEIGHT / 2, fmt_str); 253 SDL_RenderPresent(tooltip.renderer); 254 } 255} 256 257int main(int argc, char *argv[]) 258{ 259 int i; 260 261 /* Initialize test framework */ 262 state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); 263 if (!state) { 264 return 1; 265 } 266 267 /* Parse commandline */ 268 for (i = 1; i < argc;) { 269 int consumed; 270 271 consumed = SDLTest_CommonArg(state, i); 272 if (consumed == 0) { 273 consumed = -1; 274 if (SDL_strcasecmp(argv[i], "--no-constraints") == 0) { 275 no_constraints = true; 276 consumed = 1; 277 } else if (SDL_strcasecmp(argv[i], "--no-grab") == 0) { 278 no_grab = true; 279 consumed = 1; 280 } 281 } 282 if (consumed < 0) { 283 static const char *options[] = { 284 "[--no-constraints]", 285 "[--no-grab]", 286 NULL 287 }; 288 SDLTest_CommonLogUsage(state, argv[0], options); 289 return 1; 290 } 291 i += consumed; 292 } 293 294 if (!SDLTest_CommonInit(state)) { 295 SDLTest_CommonQuit(state); 296 quit(2); 297 } 298 299 for (i = 0; i < state->num_windows; ++i) { 300 SDL_Renderer *renderer = state->renderers[i]; 301 SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); 302 SDL_RenderClear(renderer); 303 } 304 305 /* Main render loop */ 306 done = 0; 307#ifdef SDL_PLATFORM_EMSCRIPTEN 308 emscripten_set_main_loop(loop, 0, 1); 309#else 310 while (!done) { 311 loop(); 312 } 313#endif 314 quit(0); 315 /* keep the compiler happy ... */ 316 return 0; 317} 318
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.