src/video/x11/SDL_x11messagebox.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 31 May 2015 22:48:26 -0400
changeset 9695 363a7880b4f7
parent 9657 fbc01731d914
child 9698 bf0257e323d2
permissions -rw-r--r--
X11: Fixed message boxes not responding to click on titlebar close button.

The window needs to catch ClientMessage events for one specific window, but
XNextEvent() catches everything, and XWindowEvent doesn't catch ClientMessage,
so we need predicate procedure and XIfEvent() here.

Fixes Bugzilla #2980.
slouken@6602
     1
/*
slouken@6602
     2
  Simple DirectMedia Layer
slouken@9619
     3
  Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
slouken@6602
     4
slouken@6602
     5
  This software is provided 'as-is', without any express or implied
slouken@6602
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@6602
     7
  arising from the use of this software.
slouken@6602
     8
slouken@6602
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@6602
    10
  including commercial applications, and to alter it and redistribute it
slouken@6602
    11
  freely, subject to the following restrictions:
slouken@6602
    12
slouken@6602
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@6602
    14
     claim that you wrote the original software. If you use this software
slouken@6602
    15
     in a product, an acknowledgment in the product documentation would be
slouken@6602
    16
     appreciated but is not required.
slouken@6602
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@6602
    18
     misrepresented as being the original software.
slouken@6602
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@6602
    20
*/
icculus@6723
    21
icculus@8093
    22
#include "../../SDL_internal.h"
slouken@6602
    23
slouken@6602
    24
#if SDL_VIDEO_DRIVER_X11
slouken@6602
    25
slouken@6602
    26
#include "SDL.h"
slouken@6602
    27
#include "SDL_x11video.h"
slouken@6602
    28
#include "SDL_x11dyn.h"
icculus@6726
    29
#include "SDL_assert.h"
slouken@6602
    30
icculus@6723
    31
#include <locale.h>
icculus@6723
    32
icculus@6726
    33
icculus@9423
    34
#define SDL_FORK_MESSAGEBOX 1
icculus@9423
    35
#define SDL_SET_LOCALE      1
icculus@6726
    36
icculus@6726
    37
#if SDL_FORK_MESSAGEBOX
icculus@6726
    38
#include <sys/types.h>
icculus@6726
    39
#include <sys/wait.h>
icculus@6726
    40
#include <unistd.h>
icculus@6726
    41
#include <errno.h>
icculus@6726
    42
#endif
icculus@6726
    43
slouken@6602
    44
#define MAX_BUTTONS             8       /* Maximum number of buttons supported */
slouken@6602
    45
#define MAX_TEXT_LINES          32      /* Maximum number of text lines supported */
slouken@6602
    46
#define MIN_BUTTON_WIDTH        64      /* Minimum button width */
slouken@6602
    47
#define MIN_DIALOG_WIDTH        200     /* Minimum dialog width */
slouken@6602
    48
#define MIN_DIALOG_HEIGHT       100     /* Minimum dialog height */
slouken@6602
    49
icculus@6723
    50
static const char g_MessageBoxFontLatin1[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
urkle@8103
    51
static const char g_MessageBoxFont[] = "-*-*-*-*-*-*-*-120-*-*-*-*-*-*";
slouken@6602
    52
slouken@6725
    53
static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] = {
icculus@6817
    54
    { 56,  54,  53  }, /* SDL_MESSAGEBOX_COLOR_BACKGROUND, */
icculus@6817
    55
    { 209, 207, 205 }, /* SDL_MESSAGEBOX_COLOR_TEXT, */
icculus@6817
    56
    { 140, 135, 129 }, /* SDL_MESSAGEBOX_COLOR_BUTTON_BORDER, */
icculus@6817
    57
    { 105, 102, 99  }, /* SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND, */
icculus@6817
    58
    { 205, 202, 53  }, /* SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED, */
slouken@6602
    59
};
slouken@6602
    60
slouken@6602
    61
#define SDL_MAKE_RGB( _r, _g, _b )  ( ( ( Uint32 )( _r ) << 16 ) | \
slouken@6602
    62
                                      ( ( Uint32 )( _g ) << 8 ) |  \
slouken@6602
    63
                                      ( ( Uint32 )( _b ) ) )
slouken@6602
    64
slouken@6725
    65
typedef struct SDL_MessageBoxButtonDataX11 {
slouken@6602
    66
    int x, y;                           /* Text position */
slouken@6602
    67
    int length;                         /* Text length */
slouken@6602
    68
    int text_width;                     /* Text width */
slouken@6602
    69
slouken@6602
    70
    SDL_Rect rect;                      /* Rectangle for entire button */
slouken@6602
    71
slouken@6602
    72
    const SDL_MessageBoxButtonData *buttondata;   /* Button data from caller */
slouken@6602
    73
} SDL_MessageBoxButtonDataX11;
slouken@6602
    74
slouken@6725
    75
typedef struct TextLineData {
slouken@6602
    76
    int width;                          /* Width of this text line */
slouken@6602
    77
    int length;                         /* String length of this text line */
slouken@6602
    78
    const char *text;                   /* Text for this line */
slouken@6602
    79
} TextLineData;
slouken@6602
    80
slouken@7522
    81
typedef struct SDL_MessageBoxDataX11
slouken@7522
    82
{
slouken@7522
    83
    Display *display;
slouken@7522
    84
    int screen;
slouken@6602
    85
    Window window;
icculus@9657
    86
#if SDL_VIDEO_DRIVER_X11_XDBE
icculus@9657
    87
    XdbeBackBuffer buf;
icculus@9657
    88
    SDL_bool xdbe;                      /* Whether Xdbe is present or not */
icculus@9657
    89
#endif
slouken@6603
    90
    long event_mask;
slouken@6602
    91
    Atom wm_protocols;
slouken@6602
    92
    Atom wm_delete_message;
slouken@6602
    93
slouken@6602
    94
    int dialog_width;                   /* Dialog box width. */
slouken@6602
    95
    int dialog_height;                  /* Dialog box height. */
slouken@6602
    96
slouken@7522
    97
    XFontSet font_set;                  /* for UTF-8 systems */
slouken@7522
    98
    XFontStruct *font_struct;           /* Latin1 (ASCII) fallback. */
slouken@6602
    99
    int xtext, ytext;                   /* Text position to start drawing at. */
slouken@6602
   100
    int numlines;                       /* Count of Text lines. */
slouken@6602
   101
    int text_height;                    /* Height for text lines. */
slouken@6602
   102
    TextLineData linedata[ MAX_TEXT_LINES ];
slouken@6602
   103
slouken@6602
   104
    int *pbuttonid;                     /* Pointer to user return buttonid value. */
slouken@6602
   105
slouken@6602
   106
    int button_press_index;             /* Index into buttondata/buttonpos for button which is pressed (or -1). */
slouken@6602
   107
    int mouse_over_index;               /* Index into buttondata/buttonpos for button mouse is over (or -1). */
slouken@6602
   108
slouken@6602
   109
    int numbuttons;                     /* Count of buttons. */
slouken@6602
   110
    const SDL_MessageBoxButtonData *buttondata;
slouken@6602
   111
    SDL_MessageBoxButtonDataX11 buttonpos[ MAX_BUTTONS ];
slouken@6602
   112
slouken@6603
   113
    Uint32 color[ SDL_MESSAGEBOX_COLOR_MAX ];
slouken@6602
   114
slouken@6602
   115
    const SDL_MessageBoxData *messageboxdata;
slouken@6602
   116
} SDL_MessageBoxDataX11;
slouken@6602
   117
slouken@6602
   118
/* Maximum helper for ints. */
slouken@7860
   119
static SDL_INLINE int
slouken@6602
   120
IntMax( int a, int b )
slouken@6602
   121
{
slouken@6602
   122
    return ( a > b  ) ? a : b;
slouken@6602
   123
}
slouken@6602
   124
slouken@6602
   125
/* Return width and height for a string. */
slouken@6602
   126
static void
icculus@6723
   127
GetTextWidthHeight( SDL_MessageBoxDataX11 *data, const char *str, int nbytes, int *pwidth, int *pheight )
slouken@6602
   128
{
icculus@6723
   129
    if (SDL_X11_HAVE_UTF8) {
icculus@6723
   130
        XRectangle overall_ink, overall_logical;
icculus@7827
   131
        X11_Xutf8TextExtents(data->font_set, str, nbytes, &overall_ink, &overall_logical);
icculus@6723
   132
        *pwidth = overall_logical.width;
icculus@6723
   133
        *pheight = overall_logical.height;
icculus@6723
   134
    } else {
icculus@6723
   135
        XCharStruct text_structure;
icculus@6723
   136
        int font_direction, font_ascent, font_descent;
icculus@7827
   137
        X11_XTextExtents( data->font_struct, str, nbytes,
icculus@6723
   138
                      &font_direction, &font_ascent, &font_descent,
icculus@6723
   139
                      &text_structure );
icculus@6723
   140
        *pwidth = text_structure.width;
icculus@6723
   141
        *pheight = text_structure.ascent + text_structure.descent;
icculus@6723
   142
    }
slouken@6602
   143
}
slouken@6602
   144
slouken@6602
   145
/* Return index of button if position x,y is contained therein. */
slouken@6602
   146
static int
slouken@6602
   147
GetHitButtonIndex( SDL_MessageBoxDataX11 *data, int x, int y )
slouken@6602
   148
{
slouken@6602
   149
    int i;
slouken@6602
   150
    int numbuttons = data->numbuttons;
slouken@6602
   151
    SDL_MessageBoxButtonDataX11 *buttonpos = data->buttonpos;
slouken@6602
   152
slouken@6725
   153
    for ( i = 0; i < numbuttons; i++ ) {
slouken@6602
   154
        SDL_Rect *rect = &buttonpos[ i ].rect;
slouken@6602
   155
slouken@6602
   156
        if ( ( x >= rect->x ) &&
slouken@6725
   157
             ( x <= ( rect->x + rect->w ) ) &&
slouken@6725
   158
             ( y >= rect->y ) &&
slouken@6725
   159
             ( y <= ( rect->y + rect->h ) ) ) {
slouken@6602
   160
            return i;
slouken@6602
   161
        }
slouken@6602
   162
    }
slouken@6602
   163
slouken@6602
   164
    return -1;
slouken@6602
   165
}
slouken@6602
   166
slouken@6602
   167
/* Initialize SDL_MessageBoxData structure and Display, etc. */
slouken@6602
   168
static int
slouken@6602
   169
X11_MessageBoxInit( SDL_MessageBoxDataX11 *data, const SDL_MessageBoxData * messageboxdata, int * pbuttonid )
slouken@6602
   170
{
slouken@6603
   171
    int i;
slouken@6602
   172
    int numbuttons = messageboxdata->numbuttons;
slouken@6602
   173
    const SDL_MessageBoxButtonData *buttondata = messageboxdata->buttons;
slouken@6603
   174
    const SDL_MessageBoxColor *colorhints;
slouken@6602
   175
slouken@6602
   176
    if ( numbuttons > MAX_BUTTONS ) {
icculus@7037
   177
        return SDL_SetError("Too many buttons (%d max allowed)", MAX_BUTTONS);
slouken@6602
   178
    }
slouken@6602
   179
slouken@6602
   180
    data->dialog_width = MIN_DIALOG_WIDTH;
slouken@6602
   181
    data->dialog_height = MIN_DIALOG_HEIGHT;
slouken@6602
   182
    data->messageboxdata = messageboxdata;
slouken@6602
   183
    data->buttondata = buttondata;
slouken@6602
   184
    data->numbuttons = numbuttons;
slouken@6602
   185
    data->pbuttonid = pbuttonid;
slouken@6602
   186
icculus@7827
   187
    data->display = X11_XOpenDisplay( NULL );
slouken@6602
   188
    if ( !data->display ) {
icculus@7037
   189
        return SDL_SetError("Couldn't open X11 display");
slouken@6602
   190
    }
slouken@6602
   191
icculus@6723
   192
    if (SDL_X11_HAVE_UTF8) {
icculus@6723
   193
        char **missing = NULL;
icculus@6723
   194
        int num_missing = 0;
icculus@7827
   195
        data->font_set = X11_XCreateFontSet(data->display, g_MessageBoxFont,
icculus@6723
   196
                                        &missing, &num_missing, NULL);
icculus@6723
   197
        if ( missing != NULL ) {
icculus@7827
   198
            X11_XFreeStringList(missing);
icculus@6723
   199
        }
icculus@6723
   200
        if ( data->font_set == NULL ) {
icculus@7037
   201
            return SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
icculus@6723
   202
        }
icculus@6723
   203
    } else {
icculus@7827
   204
        data->font_struct = X11_XLoadQueryFont( data->display, g_MessageBoxFontLatin1 );
icculus@6723
   205
        if ( data->font_struct == NULL ) {
icculus@7037
   206
            return SDL_SetError("Couldn't load font %s", g_MessageBoxFontLatin1);
icculus@6723
   207
        }
slouken@6602
   208
    }
slouken@6602
   209
slouken@6603
   210
    if ( messageboxdata->colorScheme ) {
slouken@6603
   211
        colorhints = messageboxdata->colorScheme->colors;
slouken@6603
   212
    } else {
slouken@6603
   213
        colorhints = g_default_colors;
slouken@6603
   214
    }
slouken@6602
   215
slouken@6603
   216
    /* Convert our SDL_MessageBoxColor r,g,b values to packed RGB format. */
slouken@6603
   217
    for ( i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; i++ ) {
slouken@6603
   218
        data->color[ i ] = SDL_MAKE_RGB( colorhints[ i ].r, colorhints[ i ].g, colorhints[ i ].b );
slouken@6603
   219
    }
slouken@6602
   220
slouken@6602
   221
    return 0;
slouken@6602
   222
}
slouken@6602
   223
slouken@6602
   224
/* Calculate and initialize text and button locations. */
slouken@6602
   225
static int
slouken@6602
   226
X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
slouken@6602
   227
{
slouken@6602
   228
    int i;
slouken@6602
   229
    int ybuttons;
slouken@6602
   230
    int text_width_max = 0;
slouken@6602
   231
    int button_text_height = 0;
slouken@6602
   232
    int button_width = MIN_BUTTON_WIDTH;
slouken@6602
   233
    const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
slouken@6602
   234
slouken@6602
   235
    /* Go over text and break linefeeds into separate lines. */
slouken@6725
   236
    if ( messageboxdata->message && messageboxdata->message[ 0 ] ) {
slouken@6602
   237
        const char *text = messageboxdata->message;
slouken@6602
   238
        TextLineData *plinedata = data->linedata;
slouken@6602
   239
slouken@6725
   240
        for ( i = 0; i < MAX_TEXT_LINES; i++, plinedata++ ) {
slouken@6602
   241
            int height;
slouken@6602
   242
            char *lf = SDL_strchr( ( char * )text, '\n' );
slouken@6602
   243
slouken@6602
   244
            data->numlines++;
slouken@6602
   245
slouken@6602
   246
            /* Only grab length up to lf if it exists and isn't the last line. */
slouken@6602
   247
            plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( text );
slouken@6602
   248
            plinedata->text = text;
slouken@6602
   249
icculus@6723
   250
            GetTextWidthHeight( data, text, plinedata->length, &plinedata->width, &height );
slouken@6602
   251
slouken@6602
   252
            /* Text and widths are the largest we've ever seen. */
slouken@6602
   253
            data->text_height = IntMax( data->text_height, height );
slouken@6602
   254
            text_width_max = IntMax( text_width_max, plinedata->width );
slouken@6602
   255
icculus@6758
   256
            if (lf && (lf > text) && (lf[-1] == '\r')) {
icculus@6758
   257
                plinedata->length--;
icculus@6758
   258
            }
icculus@6758
   259
slouken@6602
   260
            text += plinedata->length + 1;
slouken@6602
   261
slouken@6602
   262
            /* Break if there are no more linefeeds. */
slouken@6602
   263
            if ( !lf )
slouken@6602
   264
                break;
slouken@6602
   265
        }
slouken@6602
   266
slouken@6602
   267
        /* Bump up the text height slightly. */
slouken@6602
   268
        data->text_height += 2;
slouken@6602
   269
    }
slouken@6602
   270
slouken@6602
   271
    /* Loop through all buttons and calculate the button widths and height. */
slouken@6725
   272
    for ( i = 0; i < data->numbuttons; i++ ) {
slouken@6602
   273
        int height;
slouken@6602
   274
slouken@6602
   275
        data->buttonpos[ i ].buttondata = &data->buttondata[ i ];
slouken@6602
   276
        data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text );
slouken@6602
   277
icculus@6723
   278
        GetTextWidthHeight( data, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ),
slouken@6602
   279
                            &data->buttonpos[ i ].text_width, &height );
slouken@6602
   280
slouken@6602
   281
        button_width = IntMax( button_width, data->buttonpos[ i ].text_width );
slouken@6602
   282
        button_text_height = IntMax( button_text_height, height );
slouken@6602
   283
    }
slouken@6602
   284
slouken@6725
   285
    if ( data->numlines ) {
slouken@6602
   286
        /* x,y for this line of text. */
slouken@6602
   287
        data->xtext = data->text_height;
slouken@6602
   288
        data->ytext = data->text_height + data->text_height;
slouken@6602
   289
slouken@6602
   290
        /* Bump button y down to bottom of text. */
slouken@6602
   291
        ybuttons = 3 * data->ytext / 2 + ( data->numlines - 1 ) * data->text_height;
slouken@6602
   292
slouken@6602
   293
        /* Bump the dialog box width and height up if needed. */
slouken@6602
   294
        data->dialog_width = IntMax( data->dialog_width, 2 * data->xtext + text_width_max );
slouken@6602
   295
        data->dialog_height = IntMax( data->dialog_height, ybuttons );
slouken@6725
   296
    } else {
slouken@6602
   297
        /* Button y starts at height of button text. */
slouken@6602
   298
        ybuttons = button_text_height;
slouken@6602
   299
    }
slouken@6602
   300
slouken@6725
   301
    if ( data->numbuttons ) {
slouken@6602
   302
        int x, y;
slouken@6602
   303
        int width_of_buttons;
slouken@6602
   304
        int button_spacing = button_text_height;
slouken@6602
   305
        int button_height = 2 * button_text_height;
slouken@6602
   306
slouken@6602
   307
        /* Bump button width up a bit. */
slouken@6602
   308
        button_width += button_text_height;
slouken@6602
   309
slouken@6602
   310
        /* Get width of all buttons lined up. */
slouken@6602
   311
        width_of_buttons = data->numbuttons * button_width + ( data->numbuttons - 1 ) * button_spacing;
slouken@6602
   312
slouken@6602
   313
        /* Bump up dialog width and height if buttons are wider than text. */
slouken@6602
   314
        data->dialog_width = IntMax( data->dialog_width, width_of_buttons + 2 * button_spacing );
slouken@6602
   315
        data->dialog_height = IntMax( data->dialog_height, ybuttons + 2 * button_height );
slouken@6602
   316
slouken@6602
   317
        /* Location for first button. */
slouken@6602
   318
        x = ( data->dialog_width - width_of_buttons ) / 2;
slouken@6602
   319
        y = ybuttons + ( data->dialog_height - ybuttons - button_height ) / 2;
slouken@6602
   320
slouken@6725
   321
        for ( i = 0; i < data->numbuttons; i++ ) {
slouken@6602
   322
            /* Button coordinates. */
slouken@6602
   323
            data->buttonpos[ i ].rect.x = x;
slouken@6602
   324
            data->buttonpos[ i ].rect.y = y;
slouken@6602
   325
            data->buttonpos[ i ].rect.w = button_width;
slouken@6602
   326
            data->buttonpos[ i ].rect.h = button_height;
slouken@6602
   327
slouken@6602
   328
            /* Button text coordinates. */
slouken@6602
   329
            data->buttonpos[ i ].x = x + ( button_width - data->buttonpos[ i ].text_width ) / 2;
slouken@6602
   330
            data->buttonpos[ i ].y = y + ( button_height - button_text_height - 1 ) / 2 + button_text_height;
slouken@6602
   331
slouken@6602
   332
            /* Scoot over for next button. */
slouken@6615
   333
            x += button_width + button_spacing;
slouken@6602
   334
        }
slouken@6602
   335
    }
slouken@6602
   336
slouken@6602
   337
    return 0;
slouken@6602
   338
}
slouken@6602
   339
slouken@6602
   340
/* Free SDL_MessageBoxData data. */
slouken@6602
   341
static void
slouken@6602
   342
X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data )
slouken@6602
   343
{
slouken@6725
   344
    if ( data->font_set != NULL ) {
icculus@7827
   345
        X11_XFreeFontSet( data->display, data->font_set );
icculus@6723
   346
        data->font_set = NULL;
icculus@6723
   347
    }
icculus@6723
   348
slouken@6725
   349
    if ( data->font_struct != NULL ) {
icculus@7827
   350
        X11_XFreeFont( data->display, data->font_struct );
icculus@6723
   351
        data->font_struct = NULL;
slouken@6602
   352
    }
slouken@6602
   353
icculus@9657
   354
#if SDL_VIDEO_DRIVER_X11_XDBE
icculus@9657
   355
    if ( SDL_X11_HAVE_XDBE && data->xdbe ) {
icculus@9657
   356
        X11_XdbeDeallocateBackBufferName(data->display, data->buf);
icculus@9657
   357
    }
icculus@9657
   358
#endif
icculus@9657
   359
slouken@6725
   360
    if ( data->display ) {
slouken@6725
   361
        if ( data->window != None ) {
icculus@7827
   362
            X11_XWithdrawWindow( data->display, data->window, data->screen );
icculus@7827
   363
            X11_XDestroyWindow( data->display, data->window );
slouken@6602
   364
            data->window = None;
slouken@6602
   365
        }
slouken@6602
   366
icculus@7827
   367
        X11_XCloseDisplay( data->display );
slouken@6602
   368
        data->display = NULL;
slouken@6602
   369
    }
slouken@6602
   370
}
slouken@6602
   371
slouken@6602
   372
/* Create and set up our X11 dialog box indow. */
slouken@6602
   373
static int
slouken@6602
   374
X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data )
slouken@6602
   375
{
slouken@6602
   376
    int x, y;
slouken@6602
   377
    XSizeHints *sizehints;
slouken@6602
   378
    XSetWindowAttributes wnd_attr;
icculus@9339
   379
    Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG;
slouken@6602
   380
    Display *display = data->display;
slouken@6602
   381
    SDL_WindowData *windowdata = NULL;
slouken@6602
   382
    const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
slouken@6602
   383
slouken@6602
   384
    if ( messageboxdata->window ) {
slouken@7522
   385
        SDL_DisplayData *displaydata =
slouken@7522
   386
            (SDL_DisplayData *) SDL_GetDisplayForWindow(messageboxdata->window)->driverdata;
slouken@6602
   387
        windowdata = (SDL_WindowData *)messageboxdata->window->driverdata;
slouken@7522
   388
        data->screen = displaydata->screen;
slouken@7522
   389
    } else {
slouken@7522
   390
        data->screen = DefaultScreen( display );
slouken@6602
   391
    }
slouken@6602
   392
slouken@6602
   393
    data->event_mask = ExposureMask |
slouken@6725
   394
                       ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
slouken@6725
   395
                       StructureNotifyMask | FocusChangeMask | PointerMotionMask;
slouken@6603
   396
    wnd_attr.event_mask = data->event_mask;
slouken@6602
   397
icculus@7827
   398
    data->window = X11_XCreateWindow(
slouken@7522
   399
                       display, RootWindow(display, data->screen),
slouken@6725
   400
                       0, 0,
slouken@6725
   401
                       data->dialog_width, data->dialog_height,
slouken@6725
   402
                       0, CopyFromParent, InputOutput, CopyFromParent,
slouken@6725
   403
                       CWEventMask, &wnd_attr );
slouken@6602
   404
    if ( data->window == None ) {
icculus@7037
   405
        return SDL_SetError("Couldn't create X window");
slouken@6602
   406
    }
slouken@6602
   407
slouken@6602
   408
    if ( windowdata ) {
slouken@6602
   409
        /* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */
icculus@7827
   410
        X11_XSetTransientForHint( display, data->window, windowdata->xwindow );
slouken@6602
   411
    }
slouken@6602
   412
icculus@7827
   413
    X11_XStoreName( display, data->window, messageboxdata->title );
slouken@6602
   414
icculus@9339
   415
    /* Let the window manager know this is a dialog box */
icculus@9339
   416
    _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
icculus@9339
   417
    _NET_WM_WINDOW_TYPE_DIALOG = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
icculus@9339
   418
    X11_XChangeProperty(display, data->window, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
icculus@9339
   419
                    PropModeReplace,
icculus@9339
   420
                    (unsigned char *)&_NET_WM_WINDOW_TYPE_DIALOG, 1);
icculus@9339
   421
slouken@6602
   422
    /* Allow the window to be deleted by the window manager */
icculus@7827
   423
    data->wm_protocols = X11_XInternAtom( display, "WM_PROTOCOLS", False );
icculus@7827
   424
    data->wm_delete_message = X11_XInternAtom( display, "WM_DELETE_WINDOW", False );
icculus@7827
   425
    X11_XSetWMProtocols( display, data->window, &data->wm_delete_message, 1 );
slouken@6602
   426
slouken@6602
   427
    if ( windowdata ) {
slouken@6602
   428
        XWindowAttributes attrib;
slouken@6602
   429
        Window dummy;
slouken@6602
   430
icculus@7827
   431
        X11_XGetWindowAttributes(display, windowdata->xwindow, &attrib);
slouken@6602
   432
        x = attrib.x + ( attrib.width - data->dialog_width ) / 2;
slouken@6602
   433
        y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ;
icculus@7827
   434
        X11_XTranslateCoordinates(display, windowdata->xwindow, RootWindow(display, data->screen), x, y, &x, &y, &dummy);
slouken@6602
   435
    } else {
slouken@7522
   436
        x = ( DisplayWidth( display, data->screen ) - data->dialog_width ) / 2;
slouken@7522
   437
        y = ( DisplayHeight( display, data->screen ) - data->dialog_height ) / 3 ;
slouken@6602
   438
    }
icculus@7827
   439
    X11_XMoveWindow( display, data->window, x, y );
slouken@6602
   440
icculus@7827
   441
    sizehints = X11_XAllocSizeHints();
slouken@6602
   442
    if ( sizehints ) {
slouken@6602
   443
        sizehints->flags = USPosition | USSize | PMaxSize | PMinSize;
slouken@6602
   444
        sizehints->x = x;
slouken@6602
   445
        sizehints->y = y;
slouken@6602
   446
        sizehints->width = data->dialog_width;
slouken@6602
   447
        sizehints->height = data->dialog_height;
slouken@6602
   448
slouken@6602
   449
        sizehints->min_width = sizehints->max_width = data->dialog_width;
slouken@6602
   450
        sizehints->min_height = sizehints->max_height = data->dialog_height;
slouken@6602
   451
icculus@7827
   452
        X11_XSetWMNormalHints( display, data->window, sizehints );
slouken@6602
   453
icculus@7827
   454
        X11_XFree( sizehints );
slouken@6602
   455
    }
slouken@6602
   456
icculus@7827
   457
    X11_XMapRaised( display, data->window );
icculus@9657
   458
icculus@9657
   459
#if SDL_VIDEO_DRIVER_X11_XDBE
icculus@9657
   460
    /* Initialise a back buffer for double buffering */
icculus@9657
   461
    if (SDL_X11_HAVE_XDBE) {
icculus@9657
   462
        int xdbe_major, xdbe_minor;
icculus@9657
   463
        if (X11_XdbeQueryExtension(display, &xdbe_major, &xdbe_minor) != 0) {
icculus@9657
   464
            data->xdbe = SDL_TRUE;
icculus@9657
   465
            data->buf = X11_XdbeAllocateBackBufferName(display, data->window, XdbeUndefined);
icculus@9657
   466
        } else {
icculus@9657
   467
            data->xdbe = SDL_FALSE;
icculus@9657
   468
        }
icculus@9657
   469
    }
icculus@9657
   470
#endif
icculus@9657
   471
slouken@6602
   472
    return 0;
slouken@6602
   473
}
slouken@6602
   474
slouken@6602
   475
/* Draw our message box. */
slouken@6602
   476
static void
slouken@6602
   477
X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx )
slouken@6602
   478
{
slouken@6602
   479
    int i;
icculus@9657
   480
    Drawable window = data->window;
slouken@6602
   481
    Display *display = data->display;
slouken@6602
   482
icculus@9657
   483
#if SDL_VIDEO_DRIVER_X11_XDBE
icculus@9657
   484
    if (SDL_X11_HAVE_XDBE && data->xdbe) {
icculus@9657
   485
        window = data->buf;
icculus@9657
   486
        X11_XdbeBeginIdiom(data->display);
icculus@9657
   487
    }
icculus@9657
   488
#endif
icculus@9657
   489
icculus@7827
   490
    X11_XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ] );
icculus@7827
   491
    X11_XFillRectangle( display, window, ctx, 0, 0, data->dialog_width, data->dialog_height );
slouken@6602
   492
icculus@7827
   493
    X11_XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
slouken@6725
   494
    for ( i = 0; i < data->numlines; i++ ) {
slouken@6602
   495
        TextLineData *plinedata = &data->linedata[ i ];
slouken@6602
   496
icculus@6723
   497
        if (SDL_X11_HAVE_UTF8) {
icculus@7827
   498
            X11_Xutf8DrawString( display, window, data->font_set, ctx,
icculus@6723
   499
                             data->xtext, data->ytext + i * data->text_height,
icculus@6723
   500
                             plinedata->text, plinedata->length );
icculus@6723
   501
        } else {
icculus@7827
   502
            X11_XDrawString( display, window, ctx,
icculus@6723
   503
                         data->xtext, data->ytext + i * data->text_height,
icculus@6723
   504
                         plinedata->text, plinedata->length );
icculus@6723
   505
        }
slouken@6602
   506
    }
slouken@6602
   507
slouken@6725
   508
    for ( i = 0; i < data->numbuttons; i++ ) {
slouken@6602
   509
        SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
slouken@6602
   510
        const SDL_MessageBoxButtonData *buttondata = buttondatax11->buttondata;
slouken@6602
   511
        int border = ( buttondata->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT ) ? 2 : 0;
slouken@6602
   512
        int offset = ( ( data->mouse_over_index == i ) && ( data->button_press_index == data->mouse_over_index ) ) ? 1 : 0;
slouken@6602
   513
icculus@7827
   514
        X11_XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND ] );
icculus@7827
   515
        X11_XFillRectangle( display, window, ctx,
slouken@6602
   516
                        buttondatax11->rect.x - border, buttondatax11->rect.y - border,
slouken@6602
   517
                        buttondatax11->rect.w + 2 * border, buttondatax11->rect.h + 2 * border );
slouken@6602
   518
icculus@7827
   519
        X11_XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BORDER ] );
icculus@7827
   520
        X11_XDrawRectangle( display, window, ctx,
slouken@6602
   521
                        buttondatax11->rect.x, buttondatax11->rect.y,
slouken@6602
   522
                        buttondatax11->rect.w, buttondatax11->rect.h );
slouken@6602
   523
icculus@7827
   524
        X11_XSetForeground( display, ctx, ( data->mouse_over_index == i ) ?
slouken@6602
   525
                        data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] :
slouken@6603
   526
                        data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
icculus@6723
   527
icculus@6723
   528
        if (SDL_X11_HAVE_UTF8) {
icculus@7827
   529
            X11_Xutf8DrawString( display, window, data->font_set, ctx,
icculus@6723
   530
                             buttondatax11->x + offset,
icculus@6723
   531
                             buttondatax11->y + offset,
icculus@6723
   532
                             buttondata->text, buttondatax11->length );
icculus@6723
   533
        } else {
icculus@7827
   534
            X11_XDrawString( display, window, ctx,
icculus@6723
   535
                         buttondatax11->x + offset, buttondatax11->y + offset,
icculus@6723
   536
                         buttondata->text, buttondatax11->length );
icculus@6723
   537
        }
slouken@6602
   538
    }
icculus@9657
   539
icculus@9657
   540
#if SDL_VIDEO_DRIVER_X11_XDBE
icculus@9657
   541
    if (SDL_X11_HAVE_XDBE && data->xdbe) {
icculus@9657
   542
        XdbeSwapInfo swap_info;
icculus@9657
   543
        swap_info.swap_window = data->window;
icculus@9657
   544
        swap_info.swap_action = XdbeUndefined;
icculus@9657
   545
        X11_XdbeSwapBuffers(data->display, &swap_info, 1);
icculus@9657
   546
        X11_XdbeEndIdiom(data->display);
icculus@9657
   547
    }
icculus@9657
   548
#endif
slouken@6602
   549
}
slouken@6602
   550
icculus@9695
   551
static Bool
icculus@9695
   552
X11_MessageBoxEventTest(Display *display, XEvent *event, XPointer arg)
icculus@9695
   553
{
icculus@9695
   554
    const SDL_MessageBoxDataX11 *data = (const SDL_MessageBoxDataX11 *) arg;
icculus@9695
   555
    return ((event->xany.display == data->display) && (event->xany.window == data->window)) ? True : False;
icculus@9695
   556
}
icculus@9695
   557
slouken@6602
   558
/* Loop and handle message box event messages until something kills it. */
slouken@6602
   559
static int
slouken@6602
   560
X11_MessageBoxLoop( SDL_MessageBoxDataX11 *data )
slouken@6602
   561
{
slouken@6602
   562
    GC ctx;
slouken@6602
   563
    XGCValues ctx_vals;
slouken@6602
   564
    SDL_bool close_dialog = SDL_FALSE;
slouken@6602
   565
    SDL_bool has_focus = SDL_TRUE;
slouken@6602
   566
    KeySym last_key_pressed = XK_VoidSymbol;
icculus@6723
   567
    unsigned long gcflags = GCForeground | GCBackground;
slouken@6602
   568
icculus@6723
   569
    SDL_zero(ctx_vals);
slouken@6602
   570
    ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
slouken@6602
   571
    ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
slouken@6602
   572
icculus@6723
   573
    if (!SDL_X11_HAVE_UTF8) {
icculus@6723
   574
        gcflags |= GCFont;
icculus@6723
   575
        ctx_vals.font = data->font_struct->fid;
icculus@6723
   576
    }
icculus@6723
   577
icculus@7827
   578
    ctx = X11_XCreateGC( data->display, data->window, gcflags, &ctx_vals );
slouken@6602
   579
    if ( ctx == None ) {
icculus@7037
   580
        return SDL_SetError("Couldn't create graphics context");
slouken@6602
   581
    }
slouken@6602
   582
slouken@6602
   583
    data->button_press_index = -1;  /* Reset what button is currently depressed. */
slouken@6602
   584
    data->mouse_over_index = -1;    /* Reset what button the mouse is over. */
slouken@6602
   585
slouken@6602
   586
    while( !close_dialog ) {
slouken@6602
   587
        XEvent e;
slouken@6602
   588
        SDL_bool draw = SDL_TRUE;
slouken@6602
   589
icculus@9695
   590
        /* can't use XWindowEvent() because it can't handle ClientMessage events. */
icculus@9695
   591
        /* can't use XNextEvent() because we only want events for this window. */
icculus@9695
   592
        X11_XIfEvent( data->display, &e, X11_MessageBoxEventTest, (XPointer) data );
slouken@6602
   593
icculus@7827
   594
        /* If X11_XFilterEvent returns True, then some input method has filtered the
slouken@6602
   595
           event, and the client should discard the event. */
icculus@7827
   596
        if ( ( e.type != Expose ) && X11_XFilterEvent( &e, None ) )
slouken@6602
   597
            continue;
slouken@6602
   598
slouken@6602
   599
        switch( e.type ) {
slouken@6602
   600
        case Expose:
slouken@6602
   601
            if ( e.xexpose.count > 0 ) {
slouken@6602
   602
                draw = SDL_FALSE;
slouken@6602
   603
            }
slouken@6602
   604
            break;
slouken@6602
   605
slouken@6602
   606
        case FocusIn:
slouken@6602
   607
            /* Got focus. */
slouken@6602
   608
            has_focus = SDL_TRUE;
slouken@6602
   609
            break;
slouken@6602
   610
slouken@6602
   611
        case FocusOut:
slouken@6602
   612
            /* lost focus. Reset button and mouse info. */
slouken@6602
   613
            has_focus = SDL_FALSE;
slouken@6602
   614
            data->button_press_index = -1;
slouken@6602
   615
            data->mouse_over_index = -1;
slouken@6602
   616
            break;
slouken@6602
   617
slouken@6602
   618
        case MotionNotify:
slouken@6602
   619
            if ( has_focus ) {
slouken@6602
   620
                /* Mouse moved... */
icculus@9657
   621
                const int previndex = data->mouse_over_index;
slouken@6602
   622
                data->mouse_over_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
jorgen@8132
   623
                if (data->mouse_over_index == previndex) {
jorgen@8132
   624
                    draw = SDL_FALSE;
jorgen@8132
   625
                }
slouken@6602
   626
            }
slouken@6602
   627
            break;
slouken@6602
   628
slouken@6602
   629
        case ClientMessage:
slouken@6602
   630
            if ( e.xclient.message_type == data->wm_protocols &&
slouken@6602
   631
                 e.xclient.format == 32 &&
slouken@6602
   632
                 e.xclient.data.l[ 0 ] == data->wm_delete_message ) {
slouken@6602
   633
                close_dialog = SDL_TRUE;
slouken@6602
   634
            }
slouken@6602
   635
            break;
slouken@6602
   636
slouken@6602
   637
        case KeyPress:
slouken@6602
   638
            /* Store key press - we make sure in key release that we got both. */
icculus@7827
   639
            last_key_pressed = X11_XLookupKeysym( &e.xkey, 0 );
slouken@6602
   640
            break;
slouken@6602
   641
slouken@6725
   642
        case KeyRelease: {
slouken@6602
   643
            Uint32 mask = 0;
icculus@7827
   644
            KeySym key = X11_XLookupKeysym( &e.xkey, 0 );
slouken@6602
   645
slouken@6602
   646
            /* If this is a key release for something we didn't get the key down for, then bail. */
slouken@6602
   647
            if ( key != last_key_pressed )
slouken@6602
   648
                break;
slouken@6602
   649
slouken@6602
   650
            if ( key == XK_Escape )
slouken@6602
   651
                mask = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
slouken@6602
   652
            else if ( ( key == XK_Return ) || ( key == XK_KP_Enter ) )
slouken@6602
   653
                mask = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
slouken@6602
   654
slouken@6602
   655
            if ( mask ) {
slouken@6602
   656
                int i;
slouken@6602
   657
slouken@6602
   658
                /* Look for first button with this mask set, and return it if found. */
slouken@6602
   659
                for ( i = 0; i < data->numbuttons; i++ ) {
slouken@6602
   660
                    SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
slouken@6602
   661
slouken@6602
   662
                    if ( buttondatax11->buttondata->flags & mask ) {
slouken@6602
   663
                        *data->pbuttonid = buttondatax11->buttondata->buttonid;
slouken@6602
   664
                        close_dialog = SDL_TRUE;
slouken@6602
   665
                        break;
slouken@6602
   666
                    }
slouken@6602
   667
                }
slouken@6602
   668
            }
slouken@6602
   669
            break;
slouken@6602
   670
        }
slouken@6602
   671
slouken@6602
   672
        case ButtonPress:
slouken@6602
   673
            data->button_press_index = -1;
slouken@6602
   674
            if ( e.xbutton.button == Button1 ) {
slouken@6602
   675
                /* Find index of button they clicked on. */
slouken@6602
   676
                data->button_press_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
slouken@6602
   677
            }
slouken@6602
   678
            break;
slouken@6602
   679
slouken@6602
   680
        case ButtonRelease:
slouken@6602
   681
            /* If button is released over the same button that was clicked down on, then return it. */
slouken@6602
   682
            if ( ( e.xbutton.button == Button1 ) && ( data->button_press_index >= 0 ) ) {
slouken@6602
   683
                int button = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
slouken@6602
   684
slouken@6602
   685
                if ( data->button_press_index == button ) {
slouken@6602
   686
                    SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ button ];
slouken@6602
   687
slouken@6602
   688
                    *data->pbuttonid = buttondatax11->buttondata->buttonid;
slouken@6602
   689
                    close_dialog = SDL_TRUE;
slouken@6602
   690
                }
slouken@6602
   691
            }
slouken@6602
   692
            data->button_press_index = -1;
slouken@6602
   693
            break;
slouken@6602
   694
        }
slouken@6602
   695
slouken@6602
   696
        if ( draw ) {
slouken@6602
   697
            /* Draw our dialog box. */
slouken@6602
   698
            X11_MessageBoxDraw( data, ctx );
slouken@6602
   699
        }
slouken@6602
   700
    }
slouken@6602
   701
icculus@7827
   702
    X11_XFreeGC( data->display, ctx );
slouken@6602
   703
    return 0;
slouken@6602
   704
}
slouken@6602
   705
icculus@6726
   706
static int
icculus@6726
   707
X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid)
slouken@6602
   708
{
slouken@6602
   709
    int ret;
slouken@6602
   710
    SDL_MessageBoxDataX11 data;
mikesart@6835
   711
#if SDL_SET_LOCALE
icculus@6724
   712
    char *origlocale;
mikesart@6835
   713
#endif
slouken@6602
   714
icculus@6723
   715
    SDL_zero(data);
icculus@6723
   716
slouken@6602
   717
    if ( !SDL_X11_LoadSymbols() )
slouken@6602
   718
        return -1;
slouken@6602
   719
mikesart@6835
   720
#if SDL_SET_LOCALE
icculus@6724
   721
    origlocale = setlocale(LC_ALL, NULL);
icculus@6724
   722
    if (origlocale != NULL) {
icculus@6724
   723
        origlocale = SDL_strdup(origlocale);
icculus@6724
   724
        if (origlocale == NULL) {
icculus@7037
   725
            return SDL_OutOfMemory();
icculus@6724
   726
        }
icculus@6724
   727
        setlocale(LC_ALL, "");
icculus@6724
   728
    }
mikesart@6835
   729
#endif
icculus@6724
   730
slouken@6602
   731
    /* This code could get called from multiple threads maybe? */
icculus@7827
   732
    X11_XInitThreads();
slouken@6602
   733
slouken@6602
   734
    /* Initialize the return buttonid value to -1 (for error or dialogbox closed). */
slouken@6602
   735
    *buttonid = -1;
slouken@6602
   736
slouken@6602
   737
    /* Init and display the message box. */
slouken@6602
   738
    ret = X11_MessageBoxInit( &data, messageboxdata, buttonid );
slouken@6602
   739
    if ( ret != -1 ) {
slouken@6602
   740
        ret = X11_MessageBoxInitPositions( &data );
slouken@6602
   741
        if ( ret != -1 ) {
slouken@6602
   742
            ret = X11_MessageBoxCreateWindow( &data );
slouken@6602
   743
            if ( ret != -1 ) {
slouken@6602
   744
                ret = X11_MessageBoxLoop( &data );
slouken@6602
   745
            }
slouken@6602
   746
        }
slouken@6602
   747
    }
slouken@6602
   748
slouken@6602
   749
    X11_MessageBoxShutdown( &data );
icculus@6724
   750
mikesart@6835
   751
#if SDL_SET_LOCALE
icculus@6724
   752
    if (origlocale) {
icculus@6724
   753
        setlocale(LC_ALL, origlocale);
icculus@6724
   754
        SDL_free(origlocale);
icculus@6724
   755
    }
mikesart@6835
   756
#endif
icculus@6724
   757
slouken@6602
   758
    return ret;
slouken@6602
   759
}
slouken@6602
   760
icculus@6726
   761
/* Display an x11 message box. */
icculus@6726
   762
int
icculus@6726
   763
X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
icculus@6726
   764
{
icculus@6726
   765
#if SDL_FORK_MESSAGEBOX
icculus@6726
   766
    /* Use a child process to protect against setlocale(). Annoying. */
icculus@6726
   767
    pid_t pid;
icculus@6726
   768
    int fds[2];
icculus@6726
   769
    int status = 0;
icculus@6726
   770
icculus@6726
   771
    if (pipe(fds) == -1) {
icculus@6726
   772
        return X11_ShowMessageBoxImpl(messageboxdata, buttonid); /* oh well. */
icculus@6726
   773
    }
icculus@6726
   774
icculus@6726
   775
    pid = fork();
icculus@6726
   776
    if (pid == -1) {  /* failed */
icculus@6726
   777
        close(fds[0]);
icculus@6726
   778
        close(fds[1]);
icculus@6726
   779
        return X11_ShowMessageBoxImpl(messageboxdata, buttonid); /* oh well. */
icculus@6726
   780
    } else if (pid == 0) {  /* we're the child */
icculus@6726
   781
        int exitcode = 0;
icculus@6726
   782
        close(fds[0]);
icculus@6726
   783
        status = X11_ShowMessageBoxImpl(messageboxdata, buttonid);
icculus@6726
   784
        if (write(fds[1], &status, sizeof (int)) != sizeof (int))
icculus@6726
   785
            exitcode = 1;
icculus@6726
   786
        else if (write(fds[1], buttonid, sizeof (int)) != sizeof (int))
icculus@6726
   787
            exitcode = 1;
icculus@6726
   788
        close(fds[1]);
icculus@6726
   789
        _exit(exitcode);  /* don't run atexit() stuff, static destructors, etc. */
icculus@6726
   790
    } else {  /* we're the parent */
icculus@6726
   791
        pid_t rc;
icculus@6726
   792
        close(fds[1]);
icculus@6726
   793
        do {
icculus@6726
   794
            rc = waitpid(pid, &status, 0);
icculus@6726
   795
        } while ((rc == -1) && (errno == EINTR));
icculus@6726
   796
icculus@6726
   797
        SDL_assert(rc == pid);  /* not sure what to do if this fails. */
icculus@6726
   798
icculus@6726
   799
        if ((rc == -1) || (!WIFEXITED(status)) || (WEXITSTATUS(status) != 0)) {
icculus@7037
   800
            return SDL_SetError("msgbox child process failed");
icculus@6726
   801
        }
icculus@6726
   802
icculus@6726
   803
        if (read(fds[0], &status, sizeof (int)) != sizeof (int))
icculus@6726
   804
            status = -1;
icculus@6726
   805
        else if (read(fds[0], buttonid, sizeof (int)) != sizeof (int))
icculus@6726
   806
            status = -1;
icculus@6726
   807
        close(fds[0]);
icculus@6726
   808
icculus@6726
   809
        return status;
icculus@6726
   810
    }
icculus@6726
   811
#else
icculus@6726
   812
    return X11_ShowMessageBoxImpl(messageboxdata, buttonid);
icculus@6726
   813
#endif
icculus@6726
   814
}
slouken@6602
   815
#endif /* SDL_VIDEO_DRIVER_X11 */
slouken@6602
   816
slouken@6602
   817
/* vi: set ts=4 sw=4 expandtab: */