Make Cocoa_ShowMessageBox work in background threads.
authorJørgen P. Tjernø <jorgen@valvesoftware.com>
Mon, 22 Apr 2013 18:14:32 -0700
changeset 7088664d8532219b
parent 7087 5639ac726076
child 7089 257fc4e541e1
Make Cocoa_ShowMessageBox work in background threads.
src/video/cocoa/SDL_cocoamessagebox.m
test/testmessage.c
     1.1 --- a/src/video/cocoa/SDL_cocoamessagebox.m	Mon Apr 22 18:14:26 2013 -0700
     1.2 +++ b/src/video/cocoa/SDL_cocoamessagebox.m	Mon Apr 22 18:14:32 2013 -0700
     1.3 @@ -32,6 +32,29 @@
     1.4  #include "SDL_messagebox.h"
     1.5  #include "SDL_cocoavideo.h"
     1.6  
     1.7 +@interface SDLMessageBoxPresenter : NSObject {
     1.8 +@public
     1.9 +    NSInteger clicked;
    1.10 +}
    1.11 +@end
    1.12 +
    1.13 +@implementation SDLMessageBoxPresenter
    1.14 +- (id)init
    1.15 +{
    1.16 +    self = [super init];
    1.17 +    if (self) {
    1.18 +        clicked = -1;
    1.19 +    }
    1.20 +
    1.21 +    return self;
    1.22 +}
    1.23 +
    1.24 +- (void)showAlert:(NSAlert*)alert
    1.25 +{
    1.26 +    clicked = [alert runModal];
    1.27 +}
    1.28 +@end
    1.29 +
    1.30  
    1.31  /* Display a Cocoa message box */
    1.32  int
    1.33 @@ -41,7 +64,7 @@
    1.34  
    1.35      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    1.36  
    1.37 -    NSAlert* alert = [[NSAlert alloc] init];
    1.38 +    NSAlert* alert = [[[NSAlert alloc] init] autorelease];
    1.39  
    1.40      if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) {
    1.41          [alert setAlertStyle:NSCriticalAlertStyle];
    1.42 @@ -67,14 +90,27 @@
    1.43          }
    1.44      }
    1.45  
    1.46 -    NSInteger clicked = [alert runModal];
    1.47 -    clicked -= NSAlertFirstButtonReturn;
    1.48 -    *buttonid = buttons[clicked].buttonid;
    1.49 -    [alert release];
    1.50 +    SDLMessageBoxPresenter* presenter = [[[SDLMessageBoxPresenter alloc] init] autorelease];
    1.51 +
    1.52 +    [presenter performSelectorOnMainThread:@selector(showAlert:)
    1.53 +                                withObject:alert
    1.54 +                             waitUntilDone:YES];
    1.55 +
    1.56 +    int returnValue = 0;
    1.57 +    NSInteger clicked = presenter->clicked;
    1.58 +    if (clicked >= NSAlertFirstButtonReturn)
    1.59 +    {
    1.60 +        clicked -= NSAlertFirstButtonReturn;
    1.61 +        *buttonid = buttons[clicked].buttonid;
    1.62 +    }
    1.63 +    else
    1.64 +    {
    1.65 +        returnValue = SDL_SetError("Did not get a valid `clicked button' id: %d", clicked);
    1.66 +    }
    1.67  
    1.68      [pool release];
    1.69  
    1.70 -    return 0;
    1.71 +    return returnValue;
    1.72  }
    1.73  
    1.74  #endif /* SDL_VIDEO_DRIVER_COCOA */
     2.1 --- a/test/testmessage.c	Mon Apr 22 18:14:26 2013 -0700
     2.2 +++ b/test/testmessage.c	Mon Apr 22 18:14:32 2013 -0700
     2.3 @@ -29,13 +29,67 @@
     2.4      exit(rc);
     2.5  }
     2.6  
     2.7 +static int
     2.8 +button_messagebox(void *eventNumber)
     2.9 +{
    2.10 +    const SDL_MessageBoxButtonData buttons[] = {
    2.11 +        {
    2.12 +            SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
    2.13 +            0,
    2.14 +            "OK"
    2.15 +        },{
    2.16 +            SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
    2.17 +            1,
    2.18 +            "Cancel"
    2.19 +        },
    2.20 +    };
    2.21 +
    2.22 +    SDL_MessageBoxData data = {
    2.23 +        SDL_MESSAGEBOX_INFORMATION,
    2.24 +        NULL, // no parent window
    2.25 +        "Custom MessageBox",
    2.26 +        "This is a custom messagebox",
    2.27 +        2,
    2.28 +        buttons,
    2.29 +        NULL // Default color scheme
    2.30 +    };
    2.31 +
    2.32 +    int button = -1;
    2.33 +    int success = 0;
    2.34 +    if (eventNumber) {
    2.35 +        data.message = "This is a custom messagebox from a background thread.";
    2.36 +    }
    2.37 +
    2.38 +    success =SDL_ShowMessageBox(&data, &button);
    2.39 +    if (success == -1) {
    2.40 +        printf("Error Presenting MessageBox: %s\n", SDL_GetError());
    2.41 +        if (eventNumber) {
    2.42 +            SDL_UserEvent event;
    2.43 +            event.type = (intptr_t)eventNumber;
    2.44 +            SDL_PushEvent((SDL_Event*)&event);
    2.45 +            return 1;
    2.46 +        } else {
    2.47 +            quit(2);
    2.48 +        }
    2.49 +    }
    2.50 +    printf("Pressed button: %d, %s\n", button, button == 1 ? "Cancel" : "OK");
    2.51 +
    2.52 +    if (eventNumber) {
    2.53 +        SDL_UserEvent event;
    2.54 +        event.type = (intptr_t)eventNumber;
    2.55 +        SDL_PushEvent((SDL_Event*)&event);
    2.56 +    }
    2.57 +
    2.58 +    return 0;
    2.59 +}
    2.60 +
    2.61  int
    2.62  main(int argc, char *argv[])
    2.63  {
    2.64      int success;
    2.65  
    2.66      /* Load the SDL library */
    2.67 -    if (SDL_Init(0) < 0) {
    2.68 +    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    2.69          fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
    2.70          return (1);
    2.71      }
    2.72 @@ -78,36 +132,27 @@
    2.73          quit(1);
    2.74      }
    2.75  
    2.76 +    button_messagebox(NULL);
    2.77 +
    2.78 +    /* Technically this isn't a supported operation for the API, but it doesn't
    2.79 +     * hurt for it to work.
    2.80 +     */
    2.81      {
    2.82 -        const SDL_MessageBoxButtonData buttons[] = {
    2.83 -            {
    2.84 -                SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
    2.85 -                0,
    2.86 -                "OK"
    2.87 -            },{
    2.88 -                SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
    2.89 -                1,
    2.90 -                "Cancel"
    2.91 -            },
    2.92 -        };
    2.93 +        int status = 0;
    2.94 +        SDL_Event event;
    2.95 +        intptr_t eventNumber = SDL_RegisterEvents(1);
    2.96 +        SDL_Thread* thread = SDL_CreateThread(&button_messagebox, "MessageBox", (void*)eventNumber);
    2.97  
    2.98 -        SDL_MessageBoxData data = {
    2.99 -            SDL_MESSAGEBOX_INFORMATION,
   2.100 -            NULL, // no parent window
   2.101 -            "Custom MessageBox",
   2.102 -            "This is a custom messagebox",
   2.103 -            2,
   2.104 -            buttons,
   2.105 -            NULL // Default color scheme
   2.106 -        };
   2.107 +        while (SDL_WaitEvent(&event))
   2.108 +        {
   2.109 +            if (event.type == eventNumber) {
   2.110 +                break;
   2.111 +            }
   2.112 +        }
   2.113  
   2.114 -        int button = -1;
   2.115 -        success = SDL_ShowMessageBox(&data, &button);
   2.116 -        if (success == -1) {
   2.117 -            printf("Error Presenting MessageBox: %s\n", SDL_GetError());
   2.118 -            quit(2);
   2.119 -        }
   2.120 -        printf("Pressed button: %d, %s\n", button, button == 1 ? "Cancel" : "OK");
   2.121 +        SDL_WaitThread(thread, &status);
   2.122 +
   2.123 +        printf("Message box thread return %i\n", status);
   2.124      }
   2.125  
   2.126      SDL_Quit();