1/*
2 Copyright (C) 1997-2024 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/* Simple test of the SDL MessageBox API */
14
15#include <stdlib.h>
16
17#include <SDL3/SDL.h>
18#include <SDL3/SDL_main.h>
19#include <SDL3/SDL_test.h>
20
21/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
22static void
23quit(int rc)
24{
25 SDL_Quit();
26 /* Let 'main()' return normally */
27 if (rc != 0) {
28 exit(rc);
29 }
30}
31
32static int SDLCALL
33button_messagebox(void *eventNumber)
34{
35 const SDL_MessageBoxButtonData buttons[] = {
36 { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
37 0,
38 "OK" },
39 { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
40 1,
41 "Cancel" },
42 };
43
44 SDL_MessageBoxData data = {
45 SDL_MESSAGEBOX_INFORMATION,
46 NULL, /* no parent window */
47 "Custom MessageBox",
48 "This is a custom messagebox",
49 2,
50 NULL, /* buttons */
51 NULL /* Default color scheme */
52 };
53
54 int button = -1;
55 int success = 0;
56 data.buttons = buttons;
57 if (eventNumber) {
58 data.message = "This is a custom messagebox from a background thread.";
59 }
60
61 success = SDL_ShowMessageBox(&data, &button);
62 if (success == -1) {
63 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s\n", SDL_GetError());
64 if (eventNumber) {
65 SDL_Event event;
66 event.type = (Uint32)(intptr_t)eventNumber;
67 SDL_PushEvent(&event);
68 return 1;
69 } else {
70 quit(2);
71 }
72 }
73 SDL_Log("Pressed button: %d, %s\n", button, button == -1 ? "[closed]" : button == 1 ? "Cancel"
74 : "OK");
75
76 if (eventNumber) {
77 SDL_Event event;
78 event.type = (Uint32)(intptr_t)eventNumber;
79 SDL_PushEvent(&event);
80 }
81
82 return 0;
83}
84
85int main(int argc, char *argv[])
86{
87 int success;
88 SDLTest_CommonState *state;
89
90 /* Initialize test framework */
91 state = SDLTest_CommonCreateState(argv, 0);
92 if (!state) {
93 return 1;
94 }
95
96 /* Parse commandline */
97 if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
98 return 1;
99 }
100
101 success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
102 "Simple MessageBox",
103 "This is a simple error MessageBox",
104 NULL);
105 if (!success) {
106 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s\n", SDL_GetError());
107 quit(1);
108 }
109
110 success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
111 "Simple MessageBox",
112 "This is a simple MessageBox with a newline:\r\nHello world!",
113 NULL);
114 if (!success) {
115 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s\n", SDL_GetError());
116 quit(1);
117 }
118
119 success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
120 NULL,
121 "NULL Title",
122 NULL);
123 if (!success) {
124 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s\n", SDL_GetError());
125 quit(1);
126 }
127
128 success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
129 "NULL Message",
130 NULL,
131 NULL);
132 if (!success) {
133 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s\n", SDL_GetError());
134 quit(1);
135 }
136
137 /* Google says this is Traditional Chinese for "beef with broccoli" */
138 success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
139 "UTF-8 Simple MessageBox",
140 "Unicode text: '牛肉西蘭花' ...",
141 NULL);
142 if (!success) {
143 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s\n", SDL_GetError());
144 quit(1);
145 }
146
147 /* Google says this is Traditional Chinese for "beef with broccoli" */
148 success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
149 "UTF-8 Simple MessageBox",
150 "Unicode text and newline:\r\n'牛肉西蘭花'\n'牛肉西蘭花'",
151 NULL);
152 if (!success) {
153 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s\n", SDL_GetError());
154 quit(1);
155 }
156
157 /* Google says this is Traditional Chinese for "beef with broccoli" */
158 success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
159 "牛肉西蘭花",
160 "Unicode text in the title.",
161 NULL);
162 if (!success) {
163 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s\n", SDL_GetError());
164 quit(1);
165 }
166
167 button_messagebox(NULL);
168
169 /* Test showing a message box from a background thread.
170
171 On macOS, the video subsystem needs to be initialized for this
172 to work, since the message box events are dispatched by the Cocoa
173 subsystem on the main thread.
174 */
175 if (!SDL_Init(SDL_INIT_VIDEO)) {
176 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL video subsystem: %s\n", SDL_GetError());
177 return 1;
178 }
179 {
180 int status = 0;
181 SDL_Event event;
182 Uint32 eventNumber = SDL_RegisterEvents(1);
183 SDL_Thread *thread = SDL_CreateThread(&button_messagebox, "MessageBox", (void *)(uintptr_t)eventNumber);
184
185 while (SDL_WaitEvent(&event)) {
186 if (event.type == eventNumber) {
187 break;
188 }
189 }
190
191 SDL_WaitThread(thread, &status);
192
193 SDL_Log("Message box thread return %i\n", status);
194 }
195
196 /* Test showing a message box with a parent window */
197 {
198 SDL_Event event;
199 SDL_Window *window = SDL_CreateWindow("Test", 640, 480, 0);
200
201 /* On wayland, no window will actually show until something has
202 actually been displayed.
203 */
204 SDL_Renderer *renderer = SDL_CreateRenderer(window, NULL);
205 SDL_RenderPresent(renderer);
206
207 success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
208 "Simple MessageBox",
209 "This is a simple error MessageBox with a parent window. Press a key or close the window after dismissing this messagebox.",
210 window);
211 if (!success) {
212 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s\n", SDL_GetError());
213 quit(1);
214 }
215
216 while (SDL_WaitEvent(&event)) {
217 if (event.type == SDL_EVENT_QUIT || event.type == SDL_EVENT_KEY_UP) {
218 break;
219 }
220 }
221 }
222
223 SDL_Quit();
224 SDLTest_CommonDestroyState(state);
225 return 0;
226}