From 25a7838e2145cf4fa4bbba0fe525d4f51fd7f7b7 Mon Sep 17 00:00:00 2001 From: "J?rgen P. Tjern?" Date: Mon, 22 Apr 2013 18:14:32 -0700 Subject: [PATCH] Make Cocoa_ShowMessageBox work in background threads. --- src/video/cocoa/SDL_cocoamessagebox.m | 48 ++++++++++-- test/testmessage.c | 103 ++++++++++++++++++-------- 2 files changed, 116 insertions(+), 35 deletions(-) diff --git a/src/video/cocoa/SDL_cocoamessagebox.m b/src/video/cocoa/SDL_cocoamessagebox.m index c7b72361b..752dea0b3 100644 --- a/src/video/cocoa/SDL_cocoamessagebox.m +++ b/src/video/cocoa/SDL_cocoamessagebox.m @@ -32,6 +32,29 @@ #include "SDL_messagebox.h" #include "SDL_cocoavideo.h" +@interface SDLMessageBoxPresenter : NSObject { +@public + NSInteger clicked; +} +@end + +@implementation SDLMessageBoxPresenter +- (id)init +{ + self = [super init]; + if (self) { + clicked = -1; + } + + return self; +} + +- (void)showAlert:(NSAlert*)alert +{ + clicked = [alert runModal]; +} +@end + /* Display a Cocoa message box */ int @@ -41,7 +64,7 @@ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSAlert* alert = [[NSAlert alloc] init]; + NSAlert* alert = [[[NSAlert alloc] init] autorelease]; if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) { [alert setAlertStyle:NSCriticalAlertStyle]; @@ -67,14 +90,27 @@ } } - NSInteger clicked = [alert runModal]; - clicked -= NSAlertFirstButtonReturn; - *buttonid = buttons[clicked].buttonid; - [alert release]; + SDLMessageBoxPresenter* presenter = [[[SDLMessageBoxPresenter alloc] init] autorelease]; + + [presenter performSelectorOnMainThread:@selector(showAlert:) + withObject:alert + waitUntilDone:YES]; + + int returnValue = 0; + NSInteger clicked = presenter->clicked; + if (clicked >= NSAlertFirstButtonReturn) + { + clicked -= NSAlertFirstButtonReturn; + *buttonid = buttons[clicked].buttonid; + } + else + { + returnValue = SDL_SetError("Did not get a valid `clicked button' id: %d", clicked); + } [pool release]; - return 0; + return returnValue; } #endif /* SDL_VIDEO_DRIVER_COCOA */ diff --git a/test/testmessage.c b/test/testmessage.c index 3a8cf6be0..51aefce64 100644 --- a/test/testmessage.c +++ b/test/testmessage.c @@ -29,13 +29,67 @@ quit(int rc) exit(rc); } +static int +button_messagebox(void *eventNumber) +{ + const SDL_MessageBoxButtonData buttons[] = { + { + SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, + 0, + "OK" + },{ + SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, + 1, + "Cancel" + }, + }; + + SDL_MessageBoxData data = { + SDL_MESSAGEBOX_INFORMATION, + NULL, // no parent window + "Custom MessageBox", + "This is a custom messagebox", + 2, + buttons, + NULL // Default color scheme + }; + + int button = -1; + int success = 0; + if (eventNumber) { + data.message = "This is a custom messagebox from a background thread."; + } + + success =SDL_ShowMessageBox(&data, &button); + if (success == -1) { + printf("Error Presenting MessageBox: %s\n", SDL_GetError()); + if (eventNumber) { + SDL_UserEvent event; + event.type = (intptr_t)eventNumber; + SDL_PushEvent((SDL_Event*)&event); + return 1; + } else { + quit(2); + } + } + printf("Pressed button: %d, %s\n", button, button == 1 ? "Cancel" : "OK"); + + if (eventNumber) { + SDL_UserEvent event; + event.type = (intptr_t)eventNumber; + SDL_PushEvent((SDL_Event*)&event); + } + + return 0; +} + int main(int argc, char *argv[]) { int success; /* Load the SDL library */ - if (SDL_Init(0) < 0) { + if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); return (1); } @@ -78,36 +132,27 @@ main(int argc, char *argv[]) quit(1); } + button_messagebox(NULL); + + /* Technically this isn't a supported operation for the API, but it doesn't + * hurt for it to work. + */ { - const SDL_MessageBoxButtonData buttons[] = { - { - SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, - 0, - "OK" - },{ - SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, - 1, - "Cancel" - }, - }; - - SDL_MessageBoxData data = { - SDL_MESSAGEBOX_INFORMATION, - NULL, // no parent window - "Custom MessageBox", - "This is a custom messagebox", - 2, - buttons, - NULL // Default color scheme - }; - - int button = -1; - success = SDL_ShowMessageBox(&data, &button); - if (success == -1) { - printf("Error Presenting MessageBox: %s\n", SDL_GetError()); - quit(2); + int status = 0; + SDL_Event event; + intptr_t eventNumber = SDL_RegisterEvents(1); + SDL_Thread* thread = SDL_CreateThread(&button_messagebox, "MessageBox", (void*)eventNumber); + + while (SDL_WaitEvent(&event)) + { + if (event.type == eventNumber) { + break; + } } - printf("Pressed button: %d, %s\n", button, button == 1 ? "Cancel" : "OK"); + + SDL_WaitThread(thread, &status); + + printf("Message box thread return %i\n", status); } SDL_Quit();