Added API for simple messagebox, courtesy of Mike Sartain
authorSam Lantinga <slouken@libsdl.org>
Tue, 23 Oct 2012 17:11:22 -0700
changeset 6602533131e24aeb
parent 6601 0d0946905eb2
child 6603 fc815cb0a2de
Added API for simple messagebox, courtesy of Mike Sartain
include/SDL.h
include/SDL_messagebox.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/x11/SDL_x11messagebox.c
src/video/x11/SDL_x11sym.h
test/common.c
     1.1 --- a/include/SDL.h	Tue Oct 23 17:10:09 2012 -0700
     1.2 +++ b/include/SDL.h	Tue Oct 23 17:11:22 2012 -0700
     1.3 @@ -82,6 +82,7 @@
     1.4  #include "SDL_hints.h"
     1.5  #include "SDL_loadso.h"
     1.6  #include "SDL_log.h"
     1.7 +#include "SDL_messagebox.h"
     1.8  #include "SDL_mutex.h"
     1.9  #include "SDL_power.h"
    1.10  #include "SDL_render.h"
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/include/SDL_messagebox.h	Tue Oct 23 17:11:22 2012 -0700
     2.3 @@ -0,0 +1,140 @@
     2.4 +/*
     2.5 +  Simple DirectMedia Layer
     2.6 +  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     2.7 +
     2.8 +  This software is provided 'as-is', without any express or implied
     2.9 +  warranty.  In no event will the authors be held liable for any damages
    2.10 +  arising from the use of this software.
    2.11 +
    2.12 +  Permission is granted to anyone to use this software for any purpose,
    2.13 +  including commercial applications, and to alter it and redistribute it
    2.14 +  freely, subject to the following restrictions:
    2.15 +
    2.16 +  1. The origin of this software must not be misrepresented; you must not
    2.17 +     claim that you wrote the original software. If you use this software
    2.18 +     in a product, an acknowledgment in the product documentation would be
    2.19 +     appreciated but is not required.
    2.20 +  2. Altered source versions must be plainly marked as such, and must not be
    2.21 +     misrepresented as being the original software.
    2.22 +  3. This notice may not be removed or altered from any source distribution.
    2.23 +*/
    2.24 +
    2.25 +#ifndef _SDL_messagebox_h
    2.26 +#define _SDL_messagebox_h
    2.27 +
    2.28 +#include "SDL_stdinc.h"
    2.29 +#include "SDL_video.h"      /* For SDL_Window */
    2.30 +
    2.31 +#include "begin_code.h"
    2.32 +/* Set up for C function definitions, even when using C++ */
    2.33 +#ifdef __cplusplus
    2.34 +/* *INDENT-OFF* */
    2.35 +extern "C" {
    2.36 +/* *INDENT-ON* */
    2.37 +#endif
    2.38 +
    2.39 +/**
    2.40 + * \brief SDL_MessageBox flags. If supported will display warning icon, etc.
    2.41 + */
    2.42 +typedef enum
    2.43 +{
    2.44 +    SDL_MESSAGEBOX_ERROR        = 0x00000010,   /**< error dialog */
    2.45 +    SDL_MESSAGEBOX_WARNING      = 0x00000020,   /**< warning dialog */
    2.46 +    SDL_MESSAGEBOX_INFORMATION  = 0x00000040,   /**< informational dialog */
    2.47 +} SDL_MessageBoxFlags;
    2.48 +
    2.49 +/**
    2.50 + * \brief Flags for SDL_MessageBoxButtonData.
    2.51 + */
    2.52 +typedef enum
    2.53 +{
    2.54 +    SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 0x00000001,  /**< Marks the default button when return is hit */
    2.55 +    SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 0x00000002,  /**< Marks the default button when escape is hit */
    2.56 +} SDL_MessageBoxButtonFlags;
    2.57 +
    2.58 +/**
    2.59 + *  \brief Individual button data.
    2.60 + */
    2.61 +typedef struct
    2.62 +{
    2.63 +    Uint32 flags;       /**< ::SDL_MessageBoxButtonFlags */
    2.64 +    int buttonid;       /**< User defined button id (value returned via SDL_MessageBox) */
    2.65 +    const char * text;  /**< The UTF-8 button text */
    2.66 +} SDL_MessageBoxButtonData;
    2.67 +
    2.68 +/**
    2.69 + * \brief RGB value used in a message box color scheme
    2.70 + */
    2.71 +typedef struct
    2.72 +{
    2.73 +    Uint8 r, g, b;
    2.74 +} SDL_MessageBoxColor;
    2.75 +
    2.76 +typedef enum
    2.77 +{
    2.78 +	SDL_MESSAGEBOX_COLOR_BACKGROUND,
    2.79 +	SDL_MESSAGEBOX_COLOR_TEXT,
    2.80 +	SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,
    2.81 +	SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
    2.82 +	SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED,
    2.83 +	SDL_MESSAGEBOX_COLOR_MAX
    2.84 +} SDL_MessageBoxColorType;
    2.85 +
    2.86 +/**
    2.87 + * \brief A set of colors to use for message box dialogs
    2.88 + */
    2.89 +typedef struct
    2.90 +{
    2.91 +    SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX];
    2.92 +} SDL_MessageBoxColorScheme;
    2.93 +
    2.94 +/**
    2.95 + *  \brief MessageBox structure containing title, text, window, etc.
    2.96 + */
    2.97 +typedef struct
    2.98 +{
    2.99 +    Uint32 flags;                       /**< ::SDL_MessageBoxFlags */
   2.100 +    SDL_Window *window;                 /**< Parent window, can be NULL */
   2.101 +    const char *title;                  /**< UTF-8 title */
   2.102 +    const char *message;                /**< UTF-8 message text */
   2.103 +
   2.104 +    int numbuttons;
   2.105 +    const SDL_MessageBoxButtonData *buttons;
   2.106 +
   2.107 +    const SDL_MessageBoxColorScheme *colorScheme;   /**< ::SDL_MessageBoxColorScheme, can be NULL to use system settings */
   2.108 +} SDL_MessageBoxData;
   2.109 +
   2.110 +/**
   2.111 + *  \brief Create a modal message box.
   2.112 + *
   2.113 + *  \param messagebox The SDL_MessageBox structure with title, text, etc.
   2.114 + *
   2.115 + *  \return -1 on error, otherwise 0 and buttonid contains user id of button
   2.116 + *          hit or -1 if dialog was closed.
   2.117 + */
   2.118 +extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
   2.119 +
   2.120 +/**
   2.121 + *  \brief Create a simple modal message box
   2.122 + *
   2.123 + *  \param flags    ::SDL_MessageBoxFlags
   2.124 + *  \param title    UTF-8 title text
   2.125 + *  \param message  UTF-8 message text
   2.126 + *  \param window   The parent window, or NULL for no parent
   2.127 + *
   2.128 + *  \return 0 on success, -1 on error
   2.129 + */
   2.130 +extern DECLSPEC int SDLCALL SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window);
   2.131 +
   2.132 +
   2.133 +/* Ends C function definitions when using C++ */
   2.134 +#ifdef __cplusplus
   2.135 +/* *INDENT-OFF* */
   2.136 +}
   2.137 +/* *INDENT-ON* */
   2.138 +#endif
   2.139 +#include "close_code.h"
   2.140 +
   2.141 +#endif /* _SDL_messagebox_h */
   2.142 +
   2.143 +/* vi: set ts=4 sw=4 expandtab: */
     3.1 --- a/src/video/SDL_sysvideo.h	Tue Oct 23 17:10:09 2012 -0700
     3.2 +++ b/src/video/SDL_sysvideo.h	Tue Oct 23 17:11:22 2012 -0700
     3.3 @@ -23,6 +23,7 @@
     3.4  #ifndef _SDL_sysvideo_h
     3.5  #define _SDL_sysvideo_h
     3.6  
     3.7 +#include "SDL_messagebox.h"
     3.8  #include "SDL_shape.h"
     3.9  
    3.10  /* The SDL video driver */
    3.11 @@ -246,6 +247,9 @@
    3.12      char * (*GetClipboardText) (_THIS);
    3.13      SDL_bool (*HasClipboardText) (_THIS);
    3.14  
    3.15 +    /* MessageBox */
    3.16 +    int (*ShowMessageBox) (_THIS, const SDL_MessageBoxData *messageboxdata, int *buttonid);
    3.17 +
    3.18      /* * * */
    3.19      /* Data common to all drivers */
    3.20      SDL_bool suspend_screensaver;
     4.1 --- a/src/video/SDL_video.c	Tue Oct 23 17:10:09 2012 -0700
     4.2 +++ b/src/video/SDL_video.c	Tue Oct 23 17:11:22 2012 -0700
     4.3 @@ -2839,4 +2839,55 @@
     4.4      return SDL_FALSE;
     4.5  }
     4.6  
     4.7 +#if SDL_VIDEO_DRIVER_X11
     4.8 +extern int X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
     4.9 +#endif
    4.10 +
    4.11 +int
    4.12 +SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
    4.13 +{
    4.14 +    int dummybutton;
    4.15 +
    4.16 +    if (!buttonid) {
    4.17 +        buttonid = &dummybutton;
    4.18 +    }
    4.19 +    if (_this && _this->ShowMessageBox) {
    4.20 +        if (_this->ShowMessageBox(_this, messageboxdata, buttonid) == 0) {
    4.21 +            return 0;
    4.22 +        }
    4.23 +    }
    4.24 +
    4.25 +    /* It's completely fine to call this function before video is initialized */
    4.26 +#if SDL_VIDEO_DRIVER_X11
    4.27 +    if (X11_ShowMessageBox(messageboxdata, buttonid) == 0) {
    4.28 +        return 0;
    4.29 +    }
    4.30 +#endif
    4.31 +
    4.32 +    SDL_SetError("No message system available");
    4.33 +    return -1;
    4.34 +}
    4.35 +
    4.36 +int
    4.37 +SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window)
    4.38 +{
    4.39 +    SDL_MessageBoxData data;
    4.40 +    SDL_MessageBoxButtonData button;
    4.41 +
    4.42 +    SDL_zero(data);
    4.43 +    data.flags = flags;
    4.44 +    data.title = title;
    4.45 +    data.message = message;
    4.46 +    data.numbuttons = 1;
    4.47 +    data.buttons = &button;
    4.48 +    data.window = window;
    4.49 +
    4.50 +    SDL_zero(button);
    4.51 +    button.flags |= SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
    4.52 +    button.flags |= SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
    4.53 +    button.text = "OK";
    4.54 +
    4.55 +    return SDL_ShowMessageBox(&data, NULL);
    4.56 +}
    4.57 +
    4.58  /* vi: set ts=4 sw=4 expandtab: */
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/video/x11/SDL_x11messagebox.c	Tue Oct 23 17:11:22 2012 -0700
     5.3 @@ -0,0 +1,642 @@
     5.4 +/*
     5.5 +  Simple DirectMedia Layer
     5.6 +  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     5.7 +
     5.8 +  This software is provided 'as-is', without any express or implied
     5.9 +  warranty.  In no event will the authors be held liable for any damages
    5.10 +  arising from the use of this software.
    5.11 +
    5.12 +  Permission is granted to anyone to use this software for any purpose,
    5.13 +  including commercial applications, and to alter it and redistribute it
    5.14 +  freely, subject to the following restrictions:
    5.15 +
    5.16 +  1. The origin of this software must not be misrepresented; you must not
    5.17 +     claim that you wrote the original software. If you use this software
    5.18 +     in a product, an acknowledgment in the product documentation would be
    5.19 +     appreciated but is not required.
    5.20 +  2. Altered source versions must be plainly marked as such, and must not be
    5.21 +     misrepresented as being the original software.
    5.22 +  3. This notice may not be removed or altered from any source distribution.
    5.23 +*/
    5.24 +#include "SDL_config.h"
    5.25 +
    5.26 +#if SDL_VIDEO_DRIVER_X11
    5.27 +
    5.28 +#include "SDL.h"
    5.29 +#include "SDL_x11video.h"
    5.30 +#include "SDL_x11dyn.h"
    5.31 +
    5.32 +#define MAX_BUTTONS             8       /* Maximum number of buttons supported */
    5.33 +#define MAX_TEXT_LINES          32      /* Maximum number of text lines supported */
    5.34 +#define MIN_BUTTON_WIDTH        64      /* Minimum button width */
    5.35 +#define MIN_DIALOG_WIDTH        200     /* Minimum dialog width */
    5.36 +#define MIN_DIALOG_HEIGHT       100     /* Minimum dialog height */
    5.37 +
    5.38 +static const char g_MessageBoxFont[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
    5.39 +
    5.40 +static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] =
    5.41 +{
    5.42 +	{ 56,  54,  53  }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,       
    5.43 +	{ 209, 207, 205 }, // SDL_MESSAGEBOX_COLOR_TEXT,             
    5.44 +	{ 140, 135, 129 }, // SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,    
    5.45 +	{ 105, 102, 99  }, // SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
    5.46 +	{ 205, 202, 53  }, // SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED,  
    5.47 +};
    5.48 +
    5.49 +#define SDL_MAKE_RGB( _r, _g, _b )  ( ( ( Uint32 )( _r ) << 16 ) | \
    5.50 +                                      ( ( Uint32 )( _g ) << 8 ) |  \
    5.51 +                                      ( ( Uint32 )( _b ) ) )
    5.52 +
    5.53 +typedef struct SDL_MessageBoxButtonDataX11
    5.54 +{
    5.55 +    int x, y;                           /* Text position */
    5.56 +    int length;                         /* Text length */
    5.57 +    int text_width;                     /* Text width */
    5.58 +
    5.59 +    SDL_Rect rect;                      /* Rectangle for entire button */
    5.60 +
    5.61 +    const SDL_MessageBoxButtonData *buttondata;   /* Button data from caller */
    5.62 +} SDL_MessageBoxButtonDataX11;
    5.63 +
    5.64 +typedef struct TextLineData
    5.65 +{
    5.66 +    int width;                          /* Width of this text line */
    5.67 +    int length;                         /* String length of this text line */
    5.68 +    const char *text;                   /* Text for this line */
    5.69 +} TextLineData;
    5.70 +
    5.71 +typedef struct SDL_MessageBoxDataX11
    5.72 +{
    5.73 +    Font hfont;
    5.74 +    Window window;
    5.75 +    Display *display;
    5.76 +	long event_mask;
    5.77 +    Atom wm_protocols;
    5.78 +    Atom wm_delete_message;
    5.79 +
    5.80 +    int dialog_width;                   /* Dialog box width. */
    5.81 +    int dialog_height;                  /* Dialog box height. */
    5.82 +
    5.83 +    int xtext, ytext;                   /* Text position to start drawing at. */
    5.84 +    int numlines;                       /* Count of Text lines. */
    5.85 +    int text_height;                    /* Height for text lines. */
    5.86 +    TextLineData linedata[ MAX_TEXT_LINES ];
    5.87 +
    5.88 +    int *pbuttonid;                     /* Pointer to user return buttonid value. */
    5.89 +
    5.90 +    int button_press_index;             /* Index into buttondata/buttonpos for button which is pressed (or -1). */
    5.91 +    int mouse_over_index;               /* Index into buttondata/buttonpos for button mouse is over (or -1). */
    5.92 +
    5.93 +    int numbuttons;                     /* Count of buttons. */
    5.94 +    const SDL_MessageBoxButtonData *buttondata;
    5.95 +    SDL_MessageBoxButtonDataX11 buttonpos[ MAX_BUTTONS ];
    5.96 +
    5.97 +	Uint32 color[ SDL_MESSAGEBOX_COLOR_MAX ];
    5.98 +
    5.99 +    const SDL_MessageBoxData *messageboxdata;
   5.100 +} SDL_MessageBoxDataX11;
   5.101 +
   5.102 +/* Maximum helper for ints. */
   5.103 +static __inline__ int
   5.104 +IntMax( int a, int b )
   5.105 +{
   5.106 +    return ( a > b  ) ? a : b;
   5.107 +}
   5.108 +
   5.109 +/* Return width and height for a string. */
   5.110 +static void
   5.111 +GetTextWidthHeight( XFontStruct *font_struct, const char *str, int nchars, int *pwidth, int *pheight )
   5.112 +{
   5.113 +    XCharStruct text_structure;
   5.114 +    int font_direction, font_ascent, font_descent;
   5.115 +
   5.116 +    XTextExtents( font_struct, str, nchars,
   5.117 +                     &font_direction, &font_ascent, &font_descent,
   5.118 +                     &text_structure );
   5.119 +
   5.120 +    *pwidth = text_structure.width;
   5.121 +    *pheight = text_structure.ascent + text_structure.descent;
   5.122 +}
   5.123 +
   5.124 +/* Return index of button if position x,y is contained therein. */
   5.125 +static int
   5.126 +GetHitButtonIndex( SDL_MessageBoxDataX11 *data, int x, int y )
   5.127 +{
   5.128 +    int i;
   5.129 +    int numbuttons = data->numbuttons;
   5.130 +    SDL_MessageBoxButtonDataX11 *buttonpos = data->buttonpos;
   5.131 +
   5.132 +    for ( i = 0; i < numbuttons; i++ )
   5.133 +    {
   5.134 +        SDL_Rect *rect = &buttonpos[ i ].rect;
   5.135 +
   5.136 +        if ( ( x >= rect->x ) &&
   5.137 +            ( x <= ( rect->x + rect->w ) ) &&
   5.138 +            ( y >= rect->y ) &&
   5.139 +            ( y <= ( rect->y + rect->h ) ) )
   5.140 +        {
   5.141 +            return i;
   5.142 +        }
   5.143 +    }
   5.144 +
   5.145 +    return -1;
   5.146 +}
   5.147 +
   5.148 +/* Initialize SDL_MessageBoxData structure and Display, etc. */
   5.149 +static int
   5.150 +X11_MessageBoxInit( SDL_MessageBoxDataX11 *data, const SDL_MessageBoxData * messageboxdata, int * pbuttonid )
   5.151 +{
   5.152 +	int i;
   5.153 +    int numbuttons = messageboxdata->numbuttons;
   5.154 +    const SDL_MessageBoxButtonData *buttondata = messageboxdata->buttons;
   5.155 +	const SDL_MessageBoxColor *colorhints;
   5.156 +
   5.157 +    if ( numbuttons > MAX_BUTTONS ) {
   5.158 +        SDL_SetError("Too many buttons (%d max allowed)", MAX_BUTTONS);
   5.159 +        return -1;
   5.160 +    }
   5.161 +
   5.162 +    data->dialog_width = MIN_DIALOG_WIDTH;
   5.163 +    data->dialog_height = MIN_DIALOG_HEIGHT;
   5.164 +    data->messageboxdata = messageboxdata;
   5.165 +    data->buttondata = buttondata;
   5.166 +    data->numbuttons = numbuttons;
   5.167 +    data->pbuttonid = pbuttonid;
   5.168 +
   5.169 +    data->display = XOpenDisplay( NULL );
   5.170 +    if ( !data->display ) {
   5.171 +        SDL_SetError("Couldn't open X11 display");
   5.172 +        return -1;
   5.173 +    }
   5.174 +
   5.175 +    data->hfont = XLoadFont( data->display, g_MessageBoxFont );
   5.176 +    if ( data->hfont == None ) {
   5.177 +        SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
   5.178 +        return -1;
   5.179 +    }
   5.180 +
   5.181 +	if ( messageboxdata->colorScheme ) {
   5.182 +		colorhints = messageboxdata->colorScheme->colors;
   5.183 +	} else {
   5.184 +		colorhints = g_default_colors;
   5.185 +	}
   5.186 +
   5.187 +	/* Convert our SDL_MessageBoxColor r,g,b values to packed RGB format. */
   5.188 +	for ( i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; i++ ) {
   5.189 +		data->color[ i ] = SDL_MAKE_RGB( colorhints[ i ].r, colorhints[ i ].g, colorhints[ i ].b );
   5.190 +	}
   5.191 +
   5.192 +    return 0;
   5.193 +}
   5.194 +
   5.195 +/* Calculate and initialize text and button locations. */
   5.196 +static int
   5.197 +X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
   5.198 +{
   5.199 +    int i;
   5.200 +    int ybuttons;
   5.201 +    int text_width_max = 0;
   5.202 +    int button_text_height = 0;
   5.203 +    int button_width = MIN_BUTTON_WIDTH;
   5.204 +    const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
   5.205 +
   5.206 +    XFontStruct *fontinfo = XQueryFont( data->display, data->hfont );
   5.207 +    if ( !fontinfo ) {
   5.208 +        SDL_SetError("Couldn't get font info");
   5.209 +        return -1;
   5.210 +    }
   5.211 +
   5.212 +    /* Go over text and break linefeeds into separate lines. */
   5.213 +    if ( messageboxdata->message && messageboxdata->message[ 0 ] )
   5.214 +    {
   5.215 +        const char *text = messageboxdata->message;
   5.216 +        TextLineData *plinedata = data->linedata;
   5.217 +
   5.218 +        for ( i = 0; i < MAX_TEXT_LINES; i++, plinedata++ )
   5.219 +        {
   5.220 +            int height;
   5.221 +            char *lf = SDL_strchr( ( char * )text, '\n' );
   5.222 +
   5.223 +            data->numlines++;
   5.224 +
   5.225 +            /* Only grab length up to lf if it exists and isn't the last line. */
   5.226 +            plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( text );
   5.227 +            plinedata->text = text;
   5.228 +
   5.229 +            GetTextWidthHeight( fontinfo, text, plinedata->length, &plinedata->width, &height );
   5.230 +
   5.231 +            /* Text and widths are the largest we've ever seen. */
   5.232 +            data->text_height = IntMax( data->text_height, height );
   5.233 +            text_width_max = IntMax( text_width_max, plinedata->width );
   5.234 +
   5.235 +            text += plinedata->length + 1;
   5.236 +
   5.237 +            /* Break if there are no more linefeeds. */
   5.238 +            if ( !lf )
   5.239 +                break;
   5.240 +        }
   5.241 +
   5.242 +        /* Bump up the text height slightly. */
   5.243 +        data->text_height += 2;
   5.244 +    }
   5.245 +
   5.246 +    /* Loop through all buttons and calculate the button widths and height. */
   5.247 +    for ( i = 0; i < data->numbuttons; i++ )
   5.248 +    {
   5.249 +        int height;
   5.250 +
   5.251 +        data->buttonpos[ i ].buttondata = &data->buttondata[ i ];
   5.252 +        data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text );
   5.253 +
   5.254 +        GetTextWidthHeight( fontinfo, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ),
   5.255 +                            &data->buttonpos[ i ].text_width, &height );
   5.256 +
   5.257 +        button_width = IntMax( button_width, data->buttonpos[ i ].text_width );
   5.258 +        button_text_height = IntMax( button_text_height, height );
   5.259 +    }
   5.260 +
   5.261 +    if ( data->numlines )
   5.262 +    {
   5.263 +        /* x,y for this line of text. */
   5.264 +        data->xtext = data->text_height;
   5.265 +        data->ytext = data->text_height + data->text_height;
   5.266 +
   5.267 +        /* Bump button y down to bottom of text. */
   5.268 +        ybuttons = 3 * data->ytext / 2 + ( data->numlines - 1 ) * data->text_height;
   5.269 +
   5.270 +        /* Bump the dialog box width and height up if needed. */
   5.271 +        data->dialog_width = IntMax( data->dialog_width, 2 * data->xtext + text_width_max );
   5.272 +        data->dialog_height = IntMax( data->dialog_height, ybuttons );
   5.273 +    }
   5.274 +    else
   5.275 +    {
   5.276 +        /* Button y starts at height of button text. */
   5.277 +        ybuttons = button_text_height;
   5.278 +    }
   5.279 +
   5.280 +    if ( data->numbuttons )
   5.281 +    {
   5.282 +        int x, y;
   5.283 +        int width_of_buttons;
   5.284 +        int button_spacing = button_text_height;
   5.285 +        int button_height = 2 * button_text_height;
   5.286 +
   5.287 +        /* Bump button width up a bit. */
   5.288 +        button_width += button_text_height;
   5.289 +
   5.290 +        /* Get width of all buttons lined up. */
   5.291 +        width_of_buttons = data->numbuttons * button_width + ( data->numbuttons - 1 ) * button_spacing;
   5.292 +
   5.293 +        /* Bump up dialog width and height if buttons are wider than text. */
   5.294 +        data->dialog_width = IntMax( data->dialog_width, width_of_buttons + 2 * button_spacing );
   5.295 +        data->dialog_height = IntMax( data->dialog_height, ybuttons + 2 * button_height );
   5.296 +
   5.297 +        /* Location for first button. */
   5.298 +        x = ( data->dialog_width - width_of_buttons ) / 2;
   5.299 +        y = ybuttons + ( data->dialog_height - ybuttons - button_height ) / 2;
   5.300 +
   5.301 +        for ( i = 0; i < data->numbuttons; i++ )
   5.302 +        {
   5.303 +            /* Button coordinates. */
   5.304 +            data->buttonpos[ i ].rect.x = x;
   5.305 +            data->buttonpos[ i ].rect.y = y;
   5.306 +            data->buttonpos[ i ].rect.w = button_width;
   5.307 +            data->buttonpos[ i ].rect.h = button_height;
   5.308 +
   5.309 +            /* Button text coordinates. */
   5.310 +            data->buttonpos[ i ].x = x + ( button_width - data->buttonpos[ i ].text_width ) / 2;
   5.311 +            data->buttonpos[ i ].y = y + ( button_height - button_text_height - 1 ) / 2 + button_text_height;
   5.312 +
   5.313 +            /* Scoot over for next button. */
   5.314 +            x += button_width + button_text_height;
   5.315 +        }
   5.316 +    }
   5.317 +
   5.318 +    XFreeFontInfo( NULL, fontinfo, 1 );
   5.319 +    return 0;
   5.320 +}
   5.321 +
   5.322 +/* Free SDL_MessageBoxData data. */
   5.323 +static void
   5.324 +X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data )
   5.325 +{
   5.326 +    if ( data->hfont != None )
   5.327 +    {
   5.328 +        XUnloadFont( data->display, data->hfont );
   5.329 +        data->hfont = None;
   5.330 +    }
   5.331 +
   5.332 +    if ( data->display )
   5.333 +    {
   5.334 +        if ( data->window != None )
   5.335 +        {
   5.336 +            XUnmapWindow( data->display, data->window );
   5.337 +            XDestroyWindow( data->display, data->window );
   5.338 +            data->window = None;
   5.339 +        }
   5.340 +
   5.341 +        XCloseDisplay( data->display );
   5.342 +        data->display = NULL;
   5.343 +    }
   5.344 +}
   5.345 +
   5.346 +/* Create and set up our X11 dialog box indow. */
   5.347 +static int
   5.348 +X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data )
   5.349 +{
   5.350 +    int x, y;
   5.351 +    XSizeHints *sizehints;
   5.352 +    XSetWindowAttributes wnd_attr;
   5.353 +    Display *display = data->display;
   5.354 +    SDL_WindowData *windowdata = NULL;
   5.355 +    const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
   5.356 +
   5.357 +    if ( messageboxdata->window ) {
   5.358 +        windowdata = (SDL_WindowData *)messageboxdata->window->driverdata;
   5.359 +    }
   5.360 +
   5.361 +    data->event_mask = ExposureMask |
   5.362 +        ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
   5.363 +        StructureNotifyMask | FocusChangeMask | PointerMotionMask;
   5.364 +	wnd_attr.event_mask = data->event_mask;
   5.365 +
   5.366 +    data->window = XCreateWindow(
   5.367 +                            display, DefaultRootWindow( display ),
   5.368 +                            0, 0,
   5.369 +                            data->dialog_width, data->dialog_height,
   5.370 +                            0, CopyFromParent, InputOutput, CopyFromParent,
   5.371 +                            CWEventMask, &wnd_attr );
   5.372 +    if ( data->window == None ) {
   5.373 +        SDL_SetError("Couldn't create X window");
   5.374 +        return -1;
   5.375 +    }
   5.376 +
   5.377 +    if ( windowdata ) {
   5.378 +        /* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */
   5.379 +        XSetTransientForHint( display, data->window, windowdata->xwindow );
   5.380 +    }
   5.381 +
   5.382 +    XStoreName( display, data->window, messageboxdata->title );
   5.383 +
   5.384 +    /* Allow the window to be deleted by the window manager */
   5.385 +    data->wm_protocols = XInternAtom( display, "WM_PROTOCOLS", False );
   5.386 +    data->wm_delete_message = XInternAtom( display, "WM_DELETE_WINDOW", False );
   5.387 +    XSetWMProtocols( display, data->window, &data->wm_delete_message, 1 );
   5.388 +
   5.389 +    if ( windowdata ) {
   5.390 +        XWindowAttributes attrib;
   5.391 +        Window dummy;
   5.392 +
   5.393 +        XGetWindowAttributes(display, windowdata->xwindow, &attrib);
   5.394 +        x = attrib.x + ( attrib.width - data->dialog_width ) / 2;
   5.395 +        y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ;
   5.396 +        XTranslateCoordinates(display, windowdata->xwindow, DefaultRootWindow( display ), x, y, &x, &y, &dummy);
   5.397 +    } else {
   5.398 +        int screen = DefaultScreen( display );
   5.399 +        x = ( DisplayWidth( display, screen ) - data->dialog_width ) / 2;
   5.400 +        y = ( DisplayHeight( display, screen ) - data->dialog_height ) / 3 ;
   5.401 +    }
   5.402 +    XMoveWindow( display, data->window, x, y );
   5.403 +
   5.404 +    sizehints = XAllocSizeHints();
   5.405 +    if ( sizehints ) {
   5.406 +        sizehints->flags = USPosition | USSize | PMaxSize | PMinSize;
   5.407 +        sizehints->x = x;
   5.408 +        sizehints->y = y;
   5.409 +        sizehints->width = data->dialog_width;
   5.410 +        sizehints->height = data->dialog_height;
   5.411 +
   5.412 +        sizehints->min_width = sizehints->max_width = data->dialog_width;
   5.413 +        sizehints->min_height = sizehints->max_height = data->dialog_height;
   5.414 +
   5.415 +        XSetWMNormalHints( display, data->window, sizehints );
   5.416 +
   5.417 +        XFree( sizehints );
   5.418 +    }
   5.419 +
   5.420 +    XMapRaised( display, data->window );
   5.421 +    return 0;
   5.422 +}
   5.423 +
   5.424 +/* Draw our message box. */
   5.425 +static void
   5.426 +X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx )
   5.427 +{
   5.428 +    int i;
   5.429 +    Window window = data->window;
   5.430 +    Display *display = data->display;
   5.431 +
   5.432 +    XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ] );
   5.433 +    XFillRectangle( display, window, ctx, 0, 0, data->dialog_width, data->dialog_height );
   5.434 +
   5.435 +    XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
   5.436 +    for ( i = 0; i < data->numlines; i++ )
   5.437 +    {
   5.438 +        TextLineData *plinedata = &data->linedata[ i ];
   5.439 +
   5.440 +        XDrawString( display, window, ctx,
   5.441 +                     data->xtext, data->ytext + i * data->text_height,
   5.442 +                     plinedata->text, plinedata->length );
   5.443 +    }
   5.444 +
   5.445 +    for ( i = 0; i < data->numbuttons; i++ )
   5.446 +    {
   5.447 +        SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
   5.448 +        const SDL_MessageBoxButtonData *buttondata = buttondatax11->buttondata;
   5.449 +        int border = ( buttondata->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT ) ? 2 : 0;
   5.450 +        int offset = ( ( data->mouse_over_index == i ) && ( data->button_press_index == data->mouse_over_index ) ) ? 1 : 0;
   5.451 +
   5.452 +        XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND ] );
   5.453 +        XFillRectangle( display, window, ctx,
   5.454 +                        buttondatax11->rect.x - border, buttondatax11->rect.y - border,
   5.455 +                        buttondatax11->rect.w + 2 * border, buttondatax11->rect.h + 2 * border );
   5.456 +
   5.457 +        XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BORDER ] );
   5.458 +        XDrawRectangle( display, window, ctx,
   5.459 +                        buttondatax11->rect.x, buttondatax11->rect.y,
   5.460 +                        buttondatax11->rect.w, buttondatax11->rect.h );
   5.461 +
   5.462 +        XSetForeground( display, ctx, ( data->mouse_over_index == i ) ?
   5.463 +                        data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] :
   5.464 +						data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
   5.465 +        XDrawString( display, window, ctx,
   5.466 +            buttondatax11->x + offset, buttondatax11->y + offset,
   5.467 +            buttondata->text, buttondatax11->length );
   5.468 +    }
   5.469 +}
   5.470 +
   5.471 +/* Loop and handle message box event messages until something kills it. */
   5.472 +static int
   5.473 +X11_MessageBoxLoop( SDL_MessageBoxDataX11 *data )
   5.474 +{
   5.475 +    GC ctx;
   5.476 +    XGCValues ctx_vals;
   5.477 +    SDL_bool close_dialog = SDL_FALSE;
   5.478 +    SDL_bool has_focus = SDL_TRUE;
   5.479 +    KeySym last_key_pressed = XK_VoidSymbol;
   5.480 +
   5.481 +    ctx_vals.font = data->hfont;
   5.482 +    ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
   5.483 +    ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
   5.484 +
   5.485 +    ctx = XCreateGC( data->display, data->window, GCForeground | GCBackground | GCFont, &ctx_vals );
   5.486 +    if ( ctx == None ) {
   5.487 +        SDL_SetError("Couldn't create graphics context");
   5.488 +        return -1;
   5.489 +    }
   5.490 +
   5.491 +    data->button_press_index = -1;  /* Reset what button is currently depressed. */
   5.492 +    data->mouse_over_index = -1;    /* Reset what button the mouse is over. */
   5.493 +
   5.494 +    while( !close_dialog ) {
   5.495 +        XEvent e;
   5.496 +        SDL_bool draw = SDL_TRUE;
   5.497 +
   5.498 +		XWindowEvent( data->display, data->window, data->event_mask, &e );
   5.499 +
   5.500 +        /* If XFilterEvent returns True, then some input method has filtered the
   5.501 +           event, and the client should discard the event. */
   5.502 +        if ( ( e.type != Expose ) && XFilterEvent( &e, None ) )
   5.503 +            continue;
   5.504 +
   5.505 +        switch( e.type ) {
   5.506 +        case Expose:
   5.507 +            if ( e.xexpose.count > 0 ) {
   5.508 +                draw = SDL_FALSE;
   5.509 +            }
   5.510 +            break;
   5.511 +
   5.512 +        case FocusIn:
   5.513 +            /* Got focus. */
   5.514 +            has_focus = SDL_TRUE;
   5.515 +            break;
   5.516 +
   5.517 +        case FocusOut:
   5.518 +            /* lost focus. Reset button and mouse info. */
   5.519 +            has_focus = SDL_FALSE;
   5.520 +            data->button_press_index = -1;
   5.521 +            data->mouse_over_index = -1;
   5.522 +            break;
   5.523 +
   5.524 +        case MotionNotify:
   5.525 +            if ( has_focus ) {
   5.526 +                /* Mouse moved... */
   5.527 +                data->mouse_over_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
   5.528 +            }
   5.529 +            break;
   5.530 +
   5.531 +        case ClientMessage:
   5.532 +            if ( e.xclient.message_type == data->wm_protocols &&
   5.533 +                 e.xclient.format == 32 &&
   5.534 +                 e.xclient.data.l[ 0 ] == data->wm_delete_message ) {
   5.535 +                close_dialog = SDL_TRUE;
   5.536 +            }
   5.537 +            break;
   5.538 +
   5.539 +        case KeyPress:
   5.540 +            /* Store key press - we make sure in key release that we got both. */
   5.541 +            last_key_pressed = XLookupKeysym( &e.xkey, 0 );
   5.542 +            break;
   5.543 +
   5.544 +        case KeyRelease:
   5.545 +        {
   5.546 +            Uint32 mask = 0;
   5.547 +            KeySym key = XLookupKeysym( &e.xkey, 0 );
   5.548 +
   5.549 +            /* If this is a key release for something we didn't get the key down for, then bail. */
   5.550 +            if ( key != last_key_pressed )
   5.551 +                break;
   5.552 +
   5.553 +            if ( key == XK_Escape )
   5.554 +                mask = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
   5.555 +            else if ( ( key == XK_Return ) || ( key == XK_KP_Enter ) )
   5.556 +                mask = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
   5.557 +
   5.558 +            if ( mask ) {
   5.559 +                int i;
   5.560 +
   5.561 +                /* Look for first button with this mask set, and return it if found. */
   5.562 +                for ( i = 0; i < data->numbuttons; i++ ) {
   5.563 +                    SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
   5.564 +
   5.565 +                    if ( buttondatax11->buttondata->flags & mask ) {
   5.566 +                        *data->pbuttonid = buttondatax11->buttondata->buttonid;
   5.567 +                        close_dialog = SDL_TRUE;
   5.568 +                        break;
   5.569 +                    }
   5.570 +                }
   5.571 +            }
   5.572 +            break;
   5.573 +        }
   5.574 +
   5.575 +        case ButtonPress:
   5.576 +            data->button_press_index = -1;
   5.577 +            if ( e.xbutton.button == Button1 ) {
   5.578 +                /* Find index of button they clicked on. */
   5.579 +                data->button_press_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
   5.580 +            }
   5.581 +            break;
   5.582 +
   5.583 +        case ButtonRelease:
   5.584 +            /* If button is released over the same button that was clicked down on, then return it. */
   5.585 +            if ( ( e.xbutton.button == Button1 ) && ( data->button_press_index >= 0 ) ) {
   5.586 +                int button = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
   5.587 +
   5.588 +                if ( data->button_press_index == button ) {
   5.589 +                    SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ button ];
   5.590 +
   5.591 +                    *data->pbuttonid = buttondatax11->buttondata->buttonid;
   5.592 +                    close_dialog = SDL_TRUE;
   5.593 +                }
   5.594 +            }
   5.595 +            data->button_press_index = -1;
   5.596 +            break;
   5.597 +        }
   5.598 +
   5.599 +        if ( draw ) {
   5.600 +            /* Draw our dialog box. */
   5.601 +            X11_MessageBoxDraw( data, ctx );
   5.602 +        }
   5.603 +    }
   5.604 +
   5.605 +    XFreeGC( data->display, ctx );
   5.606 +    return 0;
   5.607 +}
   5.608 +
   5.609 +/* Display an x11 message box. */
   5.610 +int
   5.611 +X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
   5.612 +{
   5.613 +    int ret;
   5.614 +    SDL_MessageBoxDataX11 data;
   5.615 +
   5.616 +    SDL_memset( &data, 0, sizeof( data ) );
   5.617 +
   5.618 +    if ( !SDL_X11_LoadSymbols() )
   5.619 +        return -1;
   5.620 +
   5.621 +    /* This code could get called from multiple threads maybe? */
   5.622 +    XInitThreads();
   5.623 +
   5.624 +    /* Initialize the return buttonid value to -1 (for error or dialogbox closed). */
   5.625 +    *buttonid = -1;
   5.626 +
   5.627 +    /* Init and display the message box. */
   5.628 +    ret = X11_MessageBoxInit( &data, messageboxdata, buttonid );
   5.629 +    if ( ret != -1 ) {
   5.630 +        ret = X11_MessageBoxInitPositions( &data );
   5.631 +        if ( ret != -1 ) {
   5.632 +            ret = X11_MessageBoxCreateWindow( &data );
   5.633 +            if ( ret != -1 ) {
   5.634 +                ret = X11_MessageBoxLoop( &data );
   5.635 +            }
   5.636 +        }
   5.637 +    }
   5.638 +
   5.639 +    X11_MessageBoxShutdown( &data );
   5.640 +    return ret;
   5.641 +}
   5.642 +
   5.643 +#endif /* SDL_VIDEO_DRIVER_X11 */
   5.644 +
   5.645 +/* vi: set ts=4 sw=4 expandtab: */
     6.1 --- a/src/video/x11/SDL_x11sym.h	Tue Oct 23 17:10:09 2012 -0700
     6.2 +++ b/src/video/x11/SDL_x11sym.h	Tue Oct 23 17:11:22 2012 -0700
     6.3 @@ -43,13 +43,17 @@
     6.4  SDL_X11_SYM(int,XDeleteProperty,(Display* a,Window b,Atom c),(a,b,c),return)
     6.5  SDL_X11_SYM(int,XDestroyWindow,(Display* a,Window b),(a,b),return)
     6.6  SDL_X11_SYM(int,XDisplayKeycodes,(Display* a,int* b,int* c),(a,b,c),return)
     6.7 +SDL_X11_SYM(int,XDrawRectangle,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return)
     6.8  SDL_X11_SYM(char*,XDisplayName,(_Xconst char* a),(a),return)
     6.9 +SDL_X11_SYM(int,XDrawString,(Display* a,Drawable b,GC c,int d,int e,_Xconst char* f,int g),(a,b,c,d,e,f,g),return)
    6.10  SDL_X11_SYM(int,XEventsQueued,(Display* a,int b),(a,b),return)
    6.11 +SDL_X11_SYM(int,XFillRectangle,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return)
    6.12  SDL_X11_SYM(Bool,XFilterEvent,(XEvent *event,Window w),(event,w),return)
    6.13  SDL_X11_SYM(int,XFlush,(Display* a),(a),return)
    6.14  SDL_X11_SYM(int,XFree,(void*a),(a),return)
    6.15  SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return)
    6.16  SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return)
    6.17 +SDL_X11_SYM(int,XFreeFontInfo,(char** a,XFontStruct* b,int c),(a,b,c),return)
    6.18  SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return)
    6.19  SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return)
    6.20  SDL_X11_SYM(char*,XGetAtomName,(Display *a,Atom b),(a,b),return)
    6.21 @@ -73,6 +77,7 @@
    6.22  SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return)
    6.23  SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return)
    6.24  SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return)
    6.25 +SDL_X11_SYM(Font,XLoadFont,(Display* a,_Xconst char* b),(a,b),return)
    6.26  SDL_X11_SYM(KeySym,XLookupKeysym,(XKeyEvent* a,int b),(a,b),return)
    6.27  SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return)
    6.28  SDL_X11_SYM(int,XMapRaised,(Display* a,Window b),(a,b),return)
    6.29 @@ -85,6 +90,7 @@
    6.30  SDL_X11_SYM(int,XPeekEvent,(Display* a,XEvent* b),(a,b),return)
    6.31  SDL_X11_SYM(int,XPending,(Display* a),(a),return)
    6.32  SDL_X11_SYM(int,XPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j),(a,b,c,d,e,f,g,h,i,j),return)
    6.33 +SDL_X11_SYM(XFontStruct*,XQueryFont,(Display* a,XID b),(a,b),return)
    6.34  SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return)
    6.35  SDL_X11_SYM(Bool,XQueryPointer,(Display* a,Window b,Window* c,Window* d,int* e,int* f,int* g,int* h,unsigned int* i),(a,b,c,d,e,f,g,h,i),return)
    6.36  SDL_X11_SYM(int,XRaiseWindow,(Display* a,Window b),(a,b),return)
    6.37 @@ -94,6 +100,7 @@
    6.38  SDL_X11_SYM(int,XSelectInput,(Display* a,Window b,long c),(a,b,c),return)
    6.39  SDL_X11_SYM(Status,XSendEvent,(Display* a,Window b,Bool c,long d,XEvent* e),(a,b,c,d,e),return)
    6.40  SDL_X11_SYM(XErrorHandler,XSetErrorHandler,(XErrorHandler a),(a),return)
    6.41 +SDL_X11_SYM(int,XSetForeground,(Display* a,GC b,unsigned long c),(a,b,c),return)
    6.42  SDL_X11_SYM(XIOErrorHandler,XSetIOErrorHandler,(XIOErrorHandler a),(a),return)
    6.43  SDL_X11_SYM(int,XSetInputFocus,(Display *a,Window b,int c,Time d),(a,b,c,d),return)
    6.44  SDL_X11_SYM(int,XSetSelectionOwner,(Display* a,Atom b,Window c,Time d),(a,b,c,d),return)
    6.45 @@ -104,15 +111,20 @@
    6.46  SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),)
    6.47  SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return)
    6.48  SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return)
    6.49 +SDL_X11_SYM(int,XStoreName,(Display* a,Window b,_Xconst char* c),(a,b,c),return)
    6.50  SDL_X11_SYM(Status,XStringListToTextProperty,(char** a,int b,XTextProperty* c),(a,b,c),return)
    6.51  SDL_X11_SYM(int,XSync,(Display* a,Bool b),(a,b),return)
    6.52 +SDL_X11_SYM(int,XTextExtents,(XFontStruct* a,_Xconst char* b,int c,int* d,int* e,int* f,XCharStruct* g),(a,b,c,d,e,f,g),return)
    6.53 +SDL_X11_SYM(Bool,XTranslateCoordinates,(Display *a,Window b,Window c,int d,int e,int* f,int* g,Window* h),(a,b,c,d,e,f,g,h),return)
    6.54  SDL_X11_SYM(int,XUndefineCursor,(Display* a,Window b),(a,b),return)
    6.55  SDL_X11_SYM(int,XUngrabKeyboard,(Display* a,Time b),(a,b),return)
    6.56  SDL_X11_SYM(int,XUngrabPointer,(Display* a,Time b),(a,b),return)
    6.57  SDL_X11_SYM(int,XUngrabServer,(Display* a),(a),return)
    6.58  SDL_X11_SYM(int,XUninstallColormap,(Display* a,Colormap b),(a,b),return)
    6.59 +SDL_X11_SYM(int,XUnloadFont,(Display* a,Font b),(a,b),return)
    6.60  SDL_X11_SYM(int,XUnmapWindow,(Display* a,Window b),(a,b),return)
    6.61  SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned int f,unsigned int g,int h,int i),(a,b,c,d,e,f,g,h,i),return)
    6.62 +SDL_X11_SYM(int,XWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return)
    6.63  SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return)
    6.64  #if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY
    6.65  SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,_Xconst char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return)
     7.1 --- a/test/common.c	Tue Oct 23 17:10:09 2012 -0700
     7.2 +++ b/test/common.c	Tue Oct 23 17:11:22 2012 -0700
     7.3 @@ -1204,6 +1204,12 @@
     7.4                  }
     7.5              }
     7.6              break;
     7.7 +        case SDLK_1:
     7.8 +            if (event->key.keysym.mod & KMOD_CTRL) {
     7.9 +                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
    7.10 +                SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Test Message", "You're awesome!", window);
    7.11 +            }
    7.12 +            break;
    7.13          case SDLK_ESCAPE:
    7.14              *done = 1;
    7.15              break;