src/video/x11/SDL_x11messagebox.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 30 Oct 2012 12:21:15 -0700
changeset 6615 d7a463bde4d7
parent 6603 fc815cb0a2de
child 6723 7c464a9ecf48
permissions -rw-r--r--
Use the correct variable for the button spacing (even though they end up being the same thing)
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_X11
    24 
    25 #include "SDL.h"
    26 #include "SDL_x11video.h"
    27 #include "SDL_x11dyn.h"
    28 
    29 #define MAX_BUTTONS             8       /* Maximum number of buttons supported */
    30 #define MAX_TEXT_LINES          32      /* Maximum number of text lines supported */
    31 #define MIN_BUTTON_WIDTH        64      /* Minimum button width */
    32 #define MIN_DIALOG_WIDTH        200     /* Minimum dialog width */
    33 #define MIN_DIALOG_HEIGHT       100     /* Minimum dialog height */
    34 
    35 static const char g_MessageBoxFont[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
    36 
    37 static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] =
    38 {
    39     { 56,  54,  53  }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,       
    40     { 209, 207, 205 }, // SDL_MESSAGEBOX_COLOR_TEXT,             
    41     { 140, 135, 129 }, // SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,    
    42     { 105, 102, 99  }, // SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
    43     { 205, 202, 53  }, // SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED,  
    44 };
    45 
    46 #define SDL_MAKE_RGB( _r, _g, _b )  ( ( ( Uint32 )( _r ) << 16 ) | \
    47                                       ( ( Uint32 )( _g ) << 8 ) |  \
    48                                       ( ( Uint32 )( _b ) ) )
    49 
    50 typedef struct SDL_MessageBoxButtonDataX11
    51 {
    52     int x, y;                           /* Text position */
    53     int length;                         /* Text length */
    54     int text_width;                     /* Text width */
    55 
    56     SDL_Rect rect;                      /* Rectangle for entire button */
    57 
    58     const SDL_MessageBoxButtonData *buttondata;   /* Button data from caller */
    59 } SDL_MessageBoxButtonDataX11;
    60 
    61 typedef struct TextLineData
    62 {
    63     int width;                          /* Width of this text line */
    64     int length;                         /* String length of this text line */
    65     const char *text;                   /* Text for this line */
    66 } TextLineData;
    67 
    68 typedef struct SDL_MessageBoxDataX11
    69 {
    70     Font hfont;
    71     Window window;
    72     Display *display;
    73     long event_mask;
    74     Atom wm_protocols;
    75     Atom wm_delete_message;
    76 
    77     int dialog_width;                   /* Dialog box width. */
    78     int dialog_height;                  /* Dialog box height. */
    79 
    80     int xtext, ytext;                   /* Text position to start drawing at. */
    81     int numlines;                       /* Count of Text lines. */
    82     int text_height;                    /* Height for text lines. */
    83     TextLineData linedata[ MAX_TEXT_LINES ];
    84 
    85     int *pbuttonid;                     /* Pointer to user return buttonid value. */
    86 
    87     int button_press_index;             /* Index into buttondata/buttonpos for button which is pressed (or -1). */
    88     int mouse_over_index;               /* Index into buttondata/buttonpos for button mouse is over (or -1). */
    89 
    90     int numbuttons;                     /* Count of buttons. */
    91     const SDL_MessageBoxButtonData *buttondata;
    92     SDL_MessageBoxButtonDataX11 buttonpos[ MAX_BUTTONS ];
    93 
    94     Uint32 color[ SDL_MESSAGEBOX_COLOR_MAX ];
    95 
    96     const SDL_MessageBoxData *messageboxdata;
    97 } SDL_MessageBoxDataX11;
    98 
    99 /* Maximum helper for ints. */
   100 static __inline__ int
   101 IntMax( int a, int b )
   102 {
   103     return ( a > b  ) ? a : b;
   104 }
   105 
   106 /* Return width and height for a string. */
   107 static void
   108 GetTextWidthHeight( XFontStruct *font_struct, const char *str, int nchars, int *pwidth, int *pheight )
   109 {
   110     XCharStruct text_structure;
   111     int font_direction, font_ascent, font_descent;
   112 
   113     XTextExtents( font_struct, str, nchars,
   114                      &font_direction, &font_ascent, &font_descent,
   115                      &text_structure );
   116 
   117     *pwidth = text_structure.width;
   118     *pheight = text_structure.ascent + text_structure.descent;
   119 }
   120 
   121 /* Return index of button if position x,y is contained therein. */
   122 static int
   123 GetHitButtonIndex( SDL_MessageBoxDataX11 *data, int x, int y )
   124 {
   125     int i;
   126     int numbuttons = data->numbuttons;
   127     SDL_MessageBoxButtonDataX11 *buttonpos = data->buttonpos;
   128 
   129     for ( i = 0; i < numbuttons; i++ )
   130     {
   131         SDL_Rect *rect = &buttonpos[ i ].rect;
   132 
   133         if ( ( x >= rect->x ) &&
   134             ( x <= ( rect->x + rect->w ) ) &&
   135             ( y >= rect->y ) &&
   136             ( y <= ( rect->y + rect->h ) ) )
   137         {
   138             return i;
   139         }
   140     }
   141 
   142     return -1;
   143 }
   144 
   145 /* Initialize SDL_MessageBoxData structure and Display, etc. */
   146 static int
   147 X11_MessageBoxInit( SDL_MessageBoxDataX11 *data, const SDL_MessageBoxData * messageboxdata, int * pbuttonid )
   148 {
   149     int i;
   150     int numbuttons = messageboxdata->numbuttons;
   151     const SDL_MessageBoxButtonData *buttondata = messageboxdata->buttons;
   152     const SDL_MessageBoxColor *colorhints;
   153 
   154     if ( numbuttons > MAX_BUTTONS ) {
   155         SDL_SetError("Too many buttons (%d max allowed)", MAX_BUTTONS);
   156         return -1;
   157     }
   158 
   159     data->dialog_width = MIN_DIALOG_WIDTH;
   160     data->dialog_height = MIN_DIALOG_HEIGHT;
   161     data->messageboxdata = messageboxdata;
   162     data->buttondata = buttondata;
   163     data->numbuttons = numbuttons;
   164     data->pbuttonid = pbuttonid;
   165 
   166     data->display = XOpenDisplay( NULL );
   167     if ( !data->display ) {
   168         SDL_SetError("Couldn't open X11 display");
   169         return -1;
   170     }
   171 
   172     data->hfont = XLoadFont( data->display, g_MessageBoxFont );
   173     if ( data->hfont == None ) {
   174         SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
   175         return -1;
   176     }
   177 
   178     if ( messageboxdata->colorScheme ) {
   179         colorhints = messageboxdata->colorScheme->colors;
   180     } else {
   181         colorhints = g_default_colors;
   182     }
   183 
   184     /* Convert our SDL_MessageBoxColor r,g,b values to packed RGB format. */
   185     for ( i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; i++ ) {
   186         data->color[ i ] = SDL_MAKE_RGB( colorhints[ i ].r, colorhints[ i ].g, colorhints[ i ].b );
   187     }
   188 
   189     return 0;
   190 }
   191 
   192 /* Calculate and initialize text and button locations. */
   193 static int
   194 X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
   195 {
   196     int i;
   197     int ybuttons;
   198     int text_width_max = 0;
   199     int button_text_height = 0;
   200     int button_width = MIN_BUTTON_WIDTH;
   201     const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
   202 
   203     XFontStruct *fontinfo = XQueryFont( data->display, data->hfont );
   204     if ( !fontinfo ) {
   205         SDL_SetError("Couldn't get font info");
   206         return -1;
   207     }
   208 
   209     /* Go over text and break linefeeds into separate lines. */
   210     if ( messageboxdata->message && messageboxdata->message[ 0 ] )
   211     {
   212         const char *text = messageboxdata->message;
   213         TextLineData *plinedata = data->linedata;
   214 
   215         for ( i = 0; i < MAX_TEXT_LINES; i++, plinedata++ )
   216         {
   217             int height;
   218             char *lf = SDL_strchr( ( char * )text, '\n' );
   219 
   220             data->numlines++;
   221 
   222             /* Only grab length up to lf if it exists and isn't the last line. */
   223             plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( text );
   224             plinedata->text = text;
   225 
   226             GetTextWidthHeight( fontinfo, text, plinedata->length, &plinedata->width, &height );
   227 
   228             /* Text and widths are the largest we've ever seen. */
   229             data->text_height = IntMax( data->text_height, height );
   230             text_width_max = IntMax( text_width_max, plinedata->width );
   231 
   232             text += plinedata->length + 1;
   233 
   234             /* Break if there are no more linefeeds. */
   235             if ( !lf )
   236                 break;
   237         }
   238 
   239         /* Bump up the text height slightly. */
   240         data->text_height += 2;
   241     }
   242 
   243     /* Loop through all buttons and calculate the button widths and height. */
   244     for ( i = 0; i < data->numbuttons; i++ )
   245     {
   246         int height;
   247 
   248         data->buttonpos[ i ].buttondata = &data->buttondata[ i ];
   249         data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text );
   250 
   251         GetTextWidthHeight( fontinfo, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ),
   252                             &data->buttonpos[ i ].text_width, &height );
   253 
   254         button_width = IntMax( button_width, data->buttonpos[ i ].text_width );
   255         button_text_height = IntMax( button_text_height, height );
   256     }
   257 
   258     if ( data->numlines )
   259     {
   260         /* x,y for this line of text. */
   261         data->xtext = data->text_height;
   262         data->ytext = data->text_height + data->text_height;
   263 
   264         /* Bump button y down to bottom of text. */
   265         ybuttons = 3 * data->ytext / 2 + ( data->numlines - 1 ) * data->text_height;
   266 
   267         /* Bump the dialog box width and height up if needed. */
   268         data->dialog_width = IntMax( data->dialog_width, 2 * data->xtext + text_width_max );
   269         data->dialog_height = IntMax( data->dialog_height, ybuttons );
   270     }
   271     else
   272     {
   273         /* Button y starts at height of button text. */
   274         ybuttons = button_text_height;
   275     }
   276 
   277     if ( data->numbuttons )
   278     {
   279         int x, y;
   280         int width_of_buttons;
   281         int button_spacing = button_text_height;
   282         int button_height = 2 * button_text_height;
   283 
   284         /* Bump button width up a bit. */
   285         button_width += button_text_height;
   286 
   287         /* Get width of all buttons lined up. */
   288         width_of_buttons = data->numbuttons * button_width + ( data->numbuttons - 1 ) * button_spacing;
   289 
   290         /* Bump up dialog width and height if buttons are wider than text. */
   291         data->dialog_width = IntMax( data->dialog_width, width_of_buttons + 2 * button_spacing );
   292         data->dialog_height = IntMax( data->dialog_height, ybuttons + 2 * button_height );
   293 
   294         /* Location for first button. */
   295         x = ( data->dialog_width - width_of_buttons ) / 2;
   296         y = ybuttons + ( data->dialog_height - ybuttons - button_height ) / 2;
   297 
   298         for ( i = 0; i < data->numbuttons; i++ )
   299         {
   300             /* Button coordinates. */
   301             data->buttonpos[ i ].rect.x = x;
   302             data->buttonpos[ i ].rect.y = y;
   303             data->buttonpos[ i ].rect.w = button_width;
   304             data->buttonpos[ i ].rect.h = button_height;
   305 
   306             /* Button text coordinates. */
   307             data->buttonpos[ i ].x = x + ( button_width - data->buttonpos[ i ].text_width ) / 2;
   308             data->buttonpos[ i ].y = y + ( button_height - button_text_height - 1 ) / 2 + button_text_height;
   309 
   310             /* Scoot over for next button. */
   311             x += button_width + button_spacing;
   312         }
   313     }
   314 
   315     XFreeFontInfo( NULL, fontinfo, 1 );
   316     return 0;
   317 }
   318 
   319 /* Free SDL_MessageBoxData data. */
   320 static void
   321 X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data )
   322 {
   323     if ( data->hfont != None )
   324     {
   325         XUnloadFont( data->display, data->hfont );
   326         data->hfont = None;
   327     }
   328 
   329     if ( data->display )
   330     {
   331         if ( data->window != None )
   332         {
   333             XUnmapWindow( data->display, data->window );
   334             XDestroyWindow( data->display, data->window );
   335             data->window = None;
   336         }
   337 
   338         XCloseDisplay( data->display );
   339         data->display = NULL;
   340     }
   341 }
   342 
   343 /* Create and set up our X11 dialog box indow. */
   344 static int
   345 X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data )
   346 {
   347     int x, y;
   348     XSizeHints *sizehints;
   349     XSetWindowAttributes wnd_attr;
   350     Display *display = data->display;
   351     SDL_WindowData *windowdata = NULL;
   352     const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
   353 
   354     if ( messageboxdata->window ) {
   355         windowdata = (SDL_WindowData *)messageboxdata->window->driverdata;
   356     }
   357 
   358     data->event_mask = ExposureMask |
   359         ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
   360         StructureNotifyMask | FocusChangeMask | PointerMotionMask;
   361     wnd_attr.event_mask = data->event_mask;
   362 
   363     data->window = XCreateWindow(
   364                             display, DefaultRootWindow( display ),
   365                             0, 0,
   366                             data->dialog_width, data->dialog_height,
   367                             0, CopyFromParent, InputOutput, CopyFromParent,
   368                             CWEventMask, &wnd_attr );
   369     if ( data->window == None ) {
   370         SDL_SetError("Couldn't create X window");
   371         return -1;
   372     }
   373 
   374     if ( windowdata ) {
   375         /* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */
   376         XSetTransientForHint( display, data->window, windowdata->xwindow );
   377     }
   378 
   379     XStoreName( display, data->window, messageboxdata->title );
   380 
   381     /* Allow the window to be deleted by the window manager */
   382     data->wm_protocols = XInternAtom( display, "WM_PROTOCOLS", False );
   383     data->wm_delete_message = XInternAtom( display, "WM_DELETE_WINDOW", False );
   384     XSetWMProtocols( display, data->window, &data->wm_delete_message, 1 );
   385 
   386     if ( windowdata ) {
   387         XWindowAttributes attrib;
   388         Window dummy;
   389 
   390         XGetWindowAttributes(display, windowdata->xwindow, &attrib);
   391         x = attrib.x + ( attrib.width - data->dialog_width ) / 2;
   392         y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ;
   393         XTranslateCoordinates(display, windowdata->xwindow, DefaultRootWindow( display ), x, y, &x, &y, &dummy);
   394     } else {
   395         int screen = DefaultScreen( display );
   396         x = ( DisplayWidth( display, screen ) - data->dialog_width ) / 2;
   397         y = ( DisplayHeight( display, screen ) - data->dialog_height ) / 3 ;
   398     }
   399     XMoveWindow( display, data->window, x, y );
   400 
   401     sizehints = XAllocSizeHints();
   402     if ( sizehints ) {
   403         sizehints->flags = USPosition | USSize | PMaxSize | PMinSize;
   404         sizehints->x = x;
   405         sizehints->y = y;
   406         sizehints->width = data->dialog_width;
   407         sizehints->height = data->dialog_height;
   408 
   409         sizehints->min_width = sizehints->max_width = data->dialog_width;
   410         sizehints->min_height = sizehints->max_height = data->dialog_height;
   411 
   412         XSetWMNormalHints( display, data->window, sizehints );
   413 
   414         XFree( sizehints );
   415     }
   416 
   417     XMapRaised( display, data->window );
   418     return 0;
   419 }
   420 
   421 /* Draw our message box. */
   422 static void
   423 X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx )
   424 {
   425     int i;
   426     Window window = data->window;
   427     Display *display = data->display;
   428 
   429     XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ] );
   430     XFillRectangle( display, window, ctx, 0, 0, data->dialog_width, data->dialog_height );
   431 
   432     XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
   433     for ( i = 0; i < data->numlines; i++ )
   434     {
   435         TextLineData *plinedata = &data->linedata[ i ];
   436 
   437         XDrawString( display, window, ctx,
   438                      data->xtext, data->ytext + i * data->text_height,
   439                      plinedata->text, plinedata->length );
   440     }
   441 
   442     for ( i = 0; i < data->numbuttons; i++ )
   443     {
   444         SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
   445         const SDL_MessageBoxButtonData *buttondata = buttondatax11->buttondata;
   446         int border = ( buttondata->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT ) ? 2 : 0;
   447         int offset = ( ( data->mouse_over_index == i ) && ( data->button_press_index == data->mouse_over_index ) ) ? 1 : 0;
   448 
   449         XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND ] );
   450         XFillRectangle( display, window, ctx,
   451                         buttondatax11->rect.x - border, buttondatax11->rect.y - border,
   452                         buttondatax11->rect.w + 2 * border, buttondatax11->rect.h + 2 * border );
   453 
   454         XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BORDER ] );
   455         XDrawRectangle( display, window, ctx,
   456                         buttondatax11->rect.x, buttondatax11->rect.y,
   457                         buttondatax11->rect.w, buttondatax11->rect.h );
   458 
   459         XSetForeground( display, ctx, ( data->mouse_over_index == i ) ?
   460                         data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] :
   461                         data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
   462         XDrawString( display, window, ctx,
   463             buttondatax11->x + offset, buttondatax11->y + offset,
   464             buttondata->text, buttondatax11->length );
   465     }
   466 }
   467 
   468 /* Loop and handle message box event messages until something kills it. */
   469 static int
   470 X11_MessageBoxLoop( SDL_MessageBoxDataX11 *data )
   471 {
   472     GC ctx;
   473     XGCValues ctx_vals;
   474     SDL_bool close_dialog = SDL_FALSE;
   475     SDL_bool has_focus = SDL_TRUE;
   476     KeySym last_key_pressed = XK_VoidSymbol;
   477 
   478     ctx_vals.font = data->hfont;
   479     ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
   480     ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
   481 
   482     ctx = XCreateGC( data->display, data->window, GCForeground | GCBackground | GCFont, &ctx_vals );
   483     if ( ctx == None ) {
   484         SDL_SetError("Couldn't create graphics context");
   485         return -1;
   486     }
   487 
   488     data->button_press_index = -1;  /* Reset what button is currently depressed. */
   489     data->mouse_over_index = -1;    /* Reset what button the mouse is over. */
   490 
   491     while( !close_dialog ) {
   492         XEvent e;
   493         SDL_bool draw = SDL_TRUE;
   494 
   495         XWindowEvent( data->display, data->window, data->event_mask, &e );
   496 
   497         /* If XFilterEvent returns True, then some input method has filtered the
   498            event, and the client should discard the event. */
   499         if ( ( e.type != Expose ) && XFilterEvent( &e, None ) )
   500             continue;
   501 
   502         switch( e.type ) {
   503         case Expose:
   504             if ( e.xexpose.count > 0 ) {
   505                 draw = SDL_FALSE;
   506             }
   507             break;
   508 
   509         case FocusIn:
   510             /* Got focus. */
   511             has_focus = SDL_TRUE;
   512             break;
   513 
   514         case FocusOut:
   515             /* lost focus. Reset button and mouse info. */
   516             has_focus = SDL_FALSE;
   517             data->button_press_index = -1;
   518             data->mouse_over_index = -1;
   519             break;
   520 
   521         case MotionNotify:
   522             if ( has_focus ) {
   523                 /* Mouse moved... */
   524                 data->mouse_over_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
   525             }
   526             break;
   527 
   528         case ClientMessage:
   529             if ( e.xclient.message_type == data->wm_protocols &&
   530                  e.xclient.format == 32 &&
   531                  e.xclient.data.l[ 0 ] == data->wm_delete_message ) {
   532                 close_dialog = SDL_TRUE;
   533             }
   534             break;
   535 
   536         case KeyPress:
   537             /* Store key press - we make sure in key release that we got both. */
   538             last_key_pressed = XLookupKeysym( &e.xkey, 0 );
   539             break;
   540 
   541         case KeyRelease:
   542         {
   543             Uint32 mask = 0;
   544             KeySym key = XLookupKeysym( &e.xkey, 0 );
   545 
   546             /* If this is a key release for something we didn't get the key down for, then bail. */
   547             if ( key != last_key_pressed )
   548                 break;
   549 
   550             if ( key == XK_Escape )
   551                 mask = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
   552             else if ( ( key == XK_Return ) || ( key == XK_KP_Enter ) )
   553                 mask = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
   554 
   555             if ( mask ) {
   556                 int i;
   557 
   558                 /* Look for first button with this mask set, and return it if found. */
   559                 for ( i = 0; i < data->numbuttons; i++ ) {
   560                     SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
   561 
   562                     if ( buttondatax11->buttondata->flags & mask ) {
   563                         *data->pbuttonid = buttondatax11->buttondata->buttonid;
   564                         close_dialog = SDL_TRUE;
   565                         break;
   566                     }
   567                 }
   568             }
   569             break;
   570         }
   571 
   572         case ButtonPress:
   573             data->button_press_index = -1;
   574             if ( e.xbutton.button == Button1 ) {
   575                 /* Find index of button they clicked on. */
   576                 data->button_press_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
   577             }
   578             break;
   579 
   580         case ButtonRelease:
   581             /* If button is released over the same button that was clicked down on, then return it. */
   582             if ( ( e.xbutton.button == Button1 ) && ( data->button_press_index >= 0 ) ) {
   583                 int button = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
   584 
   585                 if ( data->button_press_index == button ) {
   586                     SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ button ];
   587 
   588                     *data->pbuttonid = buttondatax11->buttondata->buttonid;
   589                     close_dialog = SDL_TRUE;
   590                 }
   591             }
   592             data->button_press_index = -1;
   593             break;
   594         }
   595 
   596         if ( draw ) {
   597             /* Draw our dialog box. */
   598             X11_MessageBoxDraw( data, ctx );
   599         }
   600     }
   601 
   602     XFreeGC( data->display, ctx );
   603     return 0;
   604 }
   605 
   606 /* Display an x11 message box. */
   607 int
   608 X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
   609 {
   610     int ret;
   611     SDL_MessageBoxDataX11 data;
   612 
   613     SDL_memset( &data, 0, sizeof( data ) );
   614 
   615     if ( !SDL_X11_LoadSymbols() )
   616         return -1;
   617 
   618     /* This code could get called from multiple threads maybe? */
   619     XInitThreads();
   620 
   621     /* Initialize the return buttonid value to -1 (for error or dialogbox closed). */
   622     *buttonid = -1;
   623 
   624     /* Init and display the message box. */
   625     ret = X11_MessageBoxInit( &data, messageboxdata, buttonid );
   626     if ( ret != -1 ) {
   627         ret = X11_MessageBoxInitPositions( &data );
   628         if ( ret != -1 ) {
   629             ret = X11_MessageBoxCreateWindow( &data );
   630             if ( ret != -1 ) {
   631                 ret = X11_MessageBoxLoop( &data );
   632             }
   633         }
   634     }
   635 
   636     X11_MessageBoxShutdown( &data );
   637     return ret;
   638 }
   639 
   640 #endif /* SDL_VIDEO_DRIVER_X11 */
   641 
   642 /* vi: set ts=4 sw=4 expandtab: */