@@ -192,10 +192,181 @@ static SDL_VideoDevice *Emscripten_CreateDevice(void)
192
192
return device ;
193
193
}
194
194
195
+ static bool Emscripten_ShowMessagebox (const SDL_MessageBoxData * messageboxdata , int * buttonID ) {
196
+ if (emscripten_has_asyncify () && SDL_GetHintBoolean (SDL_HINT_EMSCRIPTEN_ASYNCIFY , true)) {
197
+ char dialog_background [32 ];
198
+ char dialog_color [32 ];
199
+ char button_border [32 ];
200
+ char button_background [32 ];
201
+ char button_hovered [32 ];
202
+
203
+ if (messageboxdata -> colorScheme ) {
204
+ SDL_MessageBoxColor color = messageboxdata -> colorScheme -> colors [SDL_MESSAGEBOX_COLOR_BACKGROUND ];
205
+ SDL_snprintf (dialog_background , sizeof (dialog_background ), "rgb(%u, %u, %u)" , color .r , color .g , color .b );
206
+
207
+ color = messageboxdata -> colorScheme -> colors [SDL_MESSAGEBOX_COLOR_TEXT ];
208
+ SDL_snprintf (dialog_color , sizeof (dialog_color ), "rgb(%u, %u, %u)" , color .r , color .g , color .b );
209
+
210
+ color = messageboxdata -> colorScheme -> colors [SDL_MESSAGEBOX_COLOR_BUTTON_BORDER ];
211
+ SDL_snprintf (button_border , sizeof (button_border ), "rgb(%u, %u, %u)" , color .r , color .g , color .b );
212
+
213
+ color = messageboxdata -> colorScheme -> colors [SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND ];
214
+ SDL_snprintf (button_background , sizeof (button_background ), "rgb(%u, %u, %u)" , color .r , color .g , color .b );
215
+
216
+ color = messageboxdata -> colorScheme -> colors [SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ];
217
+ SDL_snprintf (button_hovered , sizeof (button_hovered ), "rgb(%u, %u, %u)" , color .r , color .g , color .b );
218
+ } else {
219
+ SDL_zero (dialog_background );
220
+ SDL_zero (dialog_color );
221
+ SDL_zero (button_border );
222
+ SDL_zero (button_background );
223
+ SDL_zero (button_hovered );
224
+ }
225
+
226
+ // TODO: Handle parent window when multiple windows can be added in Emscripten builds
227
+ char dialog_id [64 ];
228
+ SDL_snprintf (dialog_id , sizeof (dialog_id ), "SDL3_messagebox_%u" , SDL_rand_bits ());
229
+ EM_ASM ({
230
+ var title = UTF8ToString ($0 );
231
+ var message = UTF8ToString ($1 );
232
+ var background = UTF8ToString ($2 );
233
+ var color = UTF8ToString ($3 );
234
+ var id = UTF8ToString ($4 );
235
+
236
+ // Dialogs are always put in the front of the DOM
237
+ var dialog = document .createElement ("dialog" );
238
+ // Set class to allow for CSS selectors
239
+ dialog .classList .add ("SDL3_messagebox" );
240
+ dialog .id = id ;
241
+ dialog .style .color = color ;
242
+ dialog .style .backgroundColor = background ;
243
+ document .body .append (dialog );
244
+
245
+ var h1 = document .createElement ("h1" );
246
+ h1 .innerText = title ;
247
+ dialog .append (h1 );
248
+
249
+ var p = document .createElement ("p" );
250
+ p .innerText = message ;
251
+ dialog .append (p );
252
+
253
+ dialog .showModal ();
254
+ }, messageboxdata -> title , messageboxdata -> message , dialog_background , dialog_color , dialog_id );
255
+
256
+ int i ;
257
+ for (i = 0 ; i < messageboxdata -> numbuttons ; ++ i ) {
258
+ SDL_MessageBoxButtonData button = messageboxdata -> buttons [i ];
259
+
260
+ const int created = EM_ASM_INT ({
261
+ var dialog_id = UTF8ToString ($0 );
262
+ var text = UTF8ToString ($1 );
263
+ var responseId = $2 ;
264
+ var clickOnReturn = $3 ;
265
+ var clickOnEscape = $4 ;
266
+ var border = UTF8ToString ($5 );
267
+ var background = UTF8ToString ($6 );
268
+ var hovered = UTF8ToString ($7 );
269
+
270
+ var dialog = document .getElementById (dialog_id );
271
+ if (!dialog ) {
272
+ return false;
273
+ }
274
+
275
+ var button = document .createElement ("button" );
276
+ button .innerText = text ;
277
+ button .style .borderColor = border ;
278
+ button .style .backgroundColor = background ;
279
+
280
+ dialog .addEventListener ('keydown' , function (e ) {
281
+ if (clickOnReturn && e .key == = "Enter" ) {
282
+ e .preventDefault ();
283
+ button .click ();
284
+ } else if (clickOnEscape && e .key == = "Escape" ) {
285
+ e .preventDefault ();
286
+ button .click ();
287
+ }
288
+ });
289
+ dialog .addEventListener ('cancel' , function (e ){
290
+ e .preventDefault ();
291
+ });
292
+
293
+ button .onmouseenter = function (e ){
294
+ button .style .backgroundColor = hovered ;
295
+ };
296
+ button .onmouseleave = function (e ){
297
+ button .style .backgroundColor = background ;
298
+ };
299
+ button .onclick = function (e ) {
300
+ dialog .close (responseId );
301
+ };
302
+
303
+ dialog .append (button );
304
+ return true;
305
+ },
306
+ dialog_id ,
307
+ button .text ,
308
+ button .buttonID ,
309
+ button .flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT ,
310
+ button .flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT ,
311
+ button_border ,
312
+ button_background ,
313
+ button_hovered
314
+ );
315
+
316
+ if (!created ) {
317
+ return false;
318
+ }
319
+ }
320
+
321
+ while (true) {
322
+ // give back control to browser for screen refresh
323
+ emscripten_sleep (0 );
324
+
325
+ const int dialog_open = EM_ASM_INT ({
326
+ var dialog_id = UTF8ToString ($0 );
327
+
328
+ var dialog = document .getElementById (dialog_id );
329
+ if (!dialog ) {
330
+ return false;
331
+ }
332
+ return dialog .open ;
333
+ }, dialog_id );
334
+
335
+ if (dialog_open ) {
336
+ continue ;
337
+ }
338
+
339
+ * buttonID = EM_ASM_INT ({
340
+ var dialog_id = UTF8ToString ($0 );
341
+ var dialog = document .getElementById (dialog_id );
342
+ if (!dialog ) {
343
+ return 0 ;
344
+ }
345
+ try
346
+ {
347
+ return parseInt (dialog .returnValue );
348
+ }
349
+ catch (e )
350
+ {
351
+ return 0 ;
352
+ }
353
+ }, dialog_id );
354
+ break ;
355
+ }
356
+
357
+ } else {
358
+ // Cannot add elements to DOM and block without Asyncify. So, fall back to the alert function.
359
+ EM_ASM ({
360
+ alert (UTF8ToString ($0 ) + "\n\n" + UTF8ToString ($1 ));
361
+ }, messageboxdata -> title , messageboxdata -> message );
362
+ }
363
+ return true;
364
+ }
365
+
195
366
VideoBootStrap Emscripten_bootstrap = {
196
367
EMSCRIPTENVID_DRIVER_NAME , "SDL emscripten video driver" ,
197
368
Emscripten_CreateDevice ,
198
- NULL , // no ShowMessageBox implementation
369
+ Emscripten_ShowMessagebox ,
199
370
false
200
371
};
201
372
0 commit comments