Added API for simple messagebox, courtesy of Mike Sartain

This commit is contained in:
Sam Lantinga 2012-10-23 17:11:22 -07:00
parent 41cb1847ac
commit 227bb9413f
7 changed files with 856 additions and 0 deletions

View file

@ -82,6 +82,7 @@
#include "SDL_hints.h" #include "SDL_hints.h"
#include "SDL_loadso.h" #include "SDL_loadso.h"
#include "SDL_log.h" #include "SDL_log.h"
#include "SDL_messagebox.h"
#include "SDL_mutex.h" #include "SDL_mutex.h"
#include "SDL_power.h" #include "SDL_power.h"
#include "SDL_render.h" #include "SDL_render.h"

140
include/SDL_messagebox.h Normal file
View file

@ -0,0 +1,140 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _SDL_messagebox_h
#define _SDL_messagebox_h
#include "SDL_stdinc.h"
#include "SDL_video.h" /* For SDL_Window */
#include "begin_code.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
/**
* \brief SDL_MessageBox flags. If supported will display warning icon, etc.
*/
typedef enum
{
SDL_MESSAGEBOX_ERROR = 0x00000010, /**< error dialog */
SDL_MESSAGEBOX_WARNING = 0x00000020, /**< warning dialog */
SDL_MESSAGEBOX_INFORMATION = 0x00000040, /**< informational dialog */
} SDL_MessageBoxFlags;
/**
* \brief Flags for SDL_MessageBoxButtonData.
*/
typedef enum
{
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 0x00000001, /**< Marks the default button when return is hit */
SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 0x00000002, /**< Marks the default button when escape is hit */
} SDL_MessageBoxButtonFlags;
/**
* \brief Individual button data.
*/
typedef struct
{
Uint32 flags; /**< ::SDL_MessageBoxButtonFlags */
int buttonid; /**< User defined button id (value returned via SDL_MessageBox) */
const char * text; /**< The UTF-8 button text */
} SDL_MessageBoxButtonData;
/**
* \brief RGB value used in a message box color scheme
*/
typedef struct
{
Uint8 r, g, b;
} SDL_MessageBoxColor;
typedef enum
{
SDL_MESSAGEBOX_COLOR_BACKGROUND,
SDL_MESSAGEBOX_COLOR_TEXT,
SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,
SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED,
SDL_MESSAGEBOX_COLOR_MAX
} SDL_MessageBoxColorType;
/**
* \brief A set of colors to use for message box dialogs
*/
typedef struct
{
SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX];
} SDL_MessageBoxColorScheme;
/**
* \brief MessageBox structure containing title, text, window, etc.
*/
typedef struct
{
Uint32 flags; /**< ::SDL_MessageBoxFlags */
SDL_Window *window; /**< Parent window, can be NULL */
const char *title; /**< UTF-8 title */
const char *message; /**< UTF-8 message text */
int numbuttons;
const SDL_MessageBoxButtonData *buttons;
const SDL_MessageBoxColorScheme *colorScheme; /**< ::SDL_MessageBoxColorScheme, can be NULL to use system settings */
} SDL_MessageBoxData;
/**
* \brief Create a modal message box.
*
* \param messagebox The SDL_MessageBox structure with title, text, etc.
*
* \return -1 on error, otherwise 0 and buttonid contains user id of button
* hit or -1 if dialog was closed.
*/
extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
/**
* \brief Create a simple modal message box
*
* \param flags ::SDL_MessageBoxFlags
* \param title UTF-8 title text
* \param message UTF-8 message text
* \param window The parent window, or NULL for no parent
*
* \return 0 on success, -1 on error
*/
extern DECLSPEC int SDLCALL SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif
#include "close_code.h"
#endif /* _SDL_messagebox_h */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -23,6 +23,7 @@
#ifndef _SDL_sysvideo_h #ifndef _SDL_sysvideo_h
#define _SDL_sysvideo_h #define _SDL_sysvideo_h
#include "SDL_messagebox.h"
#include "SDL_shape.h" #include "SDL_shape.h"
/* The SDL video driver */ /* The SDL video driver */
@ -246,6 +247,9 @@ struct SDL_VideoDevice
char * (*GetClipboardText) (_THIS); char * (*GetClipboardText) (_THIS);
SDL_bool (*HasClipboardText) (_THIS); SDL_bool (*HasClipboardText) (_THIS);
/* MessageBox */
int (*ShowMessageBox) (_THIS, const SDL_MessageBoxData *messageboxdata, int *buttonid);
/* * * */ /* * * */
/* Data common to all drivers */ /* Data common to all drivers */
SDL_bool suspend_screensaver; SDL_bool suspend_screensaver;

View file

@ -2839,4 +2839,55 @@ SDL_IsScreenKeyboardShown(SDL_Window *window)
return SDL_FALSE; return SDL_FALSE;
} }
#if SDL_VIDEO_DRIVER_X11
extern int X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
#endif
int
SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{
int dummybutton;
if (!buttonid) {
buttonid = &dummybutton;
}
if (_this && _this->ShowMessageBox) {
if (_this->ShowMessageBox(_this, messageboxdata, buttonid) == 0) {
return 0;
}
}
/* It's completely fine to call this function before video is initialized */
#if SDL_VIDEO_DRIVER_X11
if (X11_ShowMessageBox(messageboxdata, buttonid) == 0) {
return 0;
}
#endif
SDL_SetError("No message system available");
return -1;
}
int
SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window)
{
SDL_MessageBoxData data;
SDL_MessageBoxButtonData button;
SDL_zero(data);
data.flags = flags;
data.title = title;
data.message = message;
data.numbuttons = 1;
data.buttons = &button;
data.window = window;
SDL_zero(button);
button.flags |= SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
button.flags |= SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
button.text = "OK";
return SDL_ShowMessageBox(&data, NULL);
}
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

View file

@ -0,0 +1,642 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_config.h"
#if SDL_VIDEO_DRIVER_X11
#include "SDL.h"
#include "SDL_x11video.h"
#include "SDL_x11dyn.h"
#define MAX_BUTTONS 8 /* Maximum number of buttons supported */
#define MAX_TEXT_LINES 32 /* Maximum number of text lines supported */
#define MIN_BUTTON_WIDTH 64 /* Minimum button width */
#define MIN_DIALOG_WIDTH 200 /* Minimum dialog width */
#define MIN_DIALOG_HEIGHT 100 /* Minimum dialog height */
static const char g_MessageBoxFont[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] =
{
{ 56, 54, 53 }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,
{ 209, 207, 205 }, // SDL_MESSAGEBOX_COLOR_TEXT,
{ 140, 135, 129 }, // SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,
{ 105, 102, 99 }, // SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
{ 205, 202, 53 }, // SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED,
};
#define SDL_MAKE_RGB( _r, _g, _b ) ( ( ( Uint32 )( _r ) << 16 ) | \
( ( Uint32 )( _g ) << 8 ) | \
( ( Uint32 )( _b ) ) )
typedef struct SDL_MessageBoxButtonDataX11
{
int x, y; /* Text position */
int length; /* Text length */
int text_width; /* Text width */
SDL_Rect rect; /* Rectangle for entire button */
const SDL_MessageBoxButtonData *buttondata; /* Button data from caller */
} SDL_MessageBoxButtonDataX11;
typedef struct TextLineData
{
int width; /* Width of this text line */
int length; /* String length of this text line */
const char *text; /* Text for this line */
} TextLineData;
typedef struct SDL_MessageBoxDataX11
{
Font hfont;
Window window;
Display *display;
long event_mask;
Atom wm_protocols;
Atom wm_delete_message;
int dialog_width; /* Dialog box width. */
int dialog_height; /* Dialog box height. */
int xtext, ytext; /* Text position to start drawing at. */
int numlines; /* Count of Text lines. */
int text_height; /* Height for text lines. */
TextLineData linedata[ MAX_TEXT_LINES ];
int *pbuttonid; /* Pointer to user return buttonid value. */
int button_press_index; /* Index into buttondata/buttonpos for button which is pressed (or -1). */
int mouse_over_index; /* Index into buttondata/buttonpos for button mouse is over (or -1). */
int numbuttons; /* Count of buttons. */
const SDL_MessageBoxButtonData *buttondata;
SDL_MessageBoxButtonDataX11 buttonpos[ MAX_BUTTONS ];
Uint32 color[ SDL_MESSAGEBOX_COLOR_MAX ];
const SDL_MessageBoxData *messageboxdata;
} SDL_MessageBoxDataX11;
/* Maximum helper for ints. */
static __inline__ int
IntMax( int a, int b )
{
return ( a > b ) ? a : b;
}
/* Return width and height for a string. */
static void
GetTextWidthHeight( XFontStruct *font_struct, const char *str, int nchars, int *pwidth, int *pheight )
{
XCharStruct text_structure;
int font_direction, font_ascent, font_descent;
XTextExtents( font_struct, str, nchars,
&font_direction, &font_ascent, &font_descent,
&text_structure );
*pwidth = text_structure.width;
*pheight = text_structure.ascent + text_structure.descent;
}
/* Return index of button if position x,y is contained therein. */
static int
GetHitButtonIndex( SDL_MessageBoxDataX11 *data, int x, int y )
{
int i;
int numbuttons = data->numbuttons;
SDL_MessageBoxButtonDataX11 *buttonpos = data->buttonpos;
for ( i = 0; i < numbuttons; i++ )
{
SDL_Rect *rect = &buttonpos[ i ].rect;
if ( ( x >= rect->x ) &&
( x <= ( rect->x + rect->w ) ) &&
( y >= rect->y ) &&
( y <= ( rect->y + rect->h ) ) )
{
return i;
}
}
return -1;
}
/* Initialize SDL_MessageBoxData structure and Display, etc. */
static int
X11_MessageBoxInit( SDL_MessageBoxDataX11 *data, const SDL_MessageBoxData * messageboxdata, int * pbuttonid )
{
int i;
int numbuttons = messageboxdata->numbuttons;
const SDL_MessageBoxButtonData *buttondata = messageboxdata->buttons;
const SDL_MessageBoxColor *colorhints;
if ( numbuttons > MAX_BUTTONS ) {
SDL_SetError("Too many buttons (%d max allowed)", MAX_BUTTONS);
return -1;
}
data->dialog_width = MIN_DIALOG_WIDTH;
data->dialog_height = MIN_DIALOG_HEIGHT;
data->messageboxdata = messageboxdata;
data->buttondata = buttondata;
data->numbuttons = numbuttons;
data->pbuttonid = pbuttonid;
data->display = XOpenDisplay( NULL );
if ( !data->display ) {
SDL_SetError("Couldn't open X11 display");
return -1;
}
data->hfont = XLoadFont( data->display, g_MessageBoxFont );
if ( data->hfont == None ) {
SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
return -1;
}
if ( messageboxdata->colorScheme ) {
colorhints = messageboxdata->colorScheme->colors;
} else {
colorhints = g_default_colors;
}
/* Convert our SDL_MessageBoxColor r,g,b values to packed RGB format. */
for ( i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; i++ ) {
data->color[ i ] = SDL_MAKE_RGB( colorhints[ i ].r, colorhints[ i ].g, colorhints[ i ].b );
}
return 0;
}
/* Calculate and initialize text and button locations. */
static int
X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
{
int i;
int ybuttons;
int text_width_max = 0;
int button_text_height = 0;
int button_width = MIN_BUTTON_WIDTH;
const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
XFontStruct *fontinfo = XQueryFont( data->display, data->hfont );
if ( !fontinfo ) {
SDL_SetError("Couldn't get font info");
return -1;
}
/* Go over text and break linefeeds into separate lines. */
if ( messageboxdata->message && messageboxdata->message[ 0 ] )
{
const char *text = messageboxdata->message;
TextLineData *plinedata = data->linedata;
for ( i = 0; i < MAX_TEXT_LINES; i++, plinedata++ )
{
int height;
char *lf = SDL_strchr( ( char * )text, '\n' );
data->numlines++;
/* Only grab length up to lf if it exists and isn't the last line. */
plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( text );
plinedata->text = text;
GetTextWidthHeight( fontinfo, text, plinedata->length, &plinedata->width, &height );
/* Text and widths are the largest we've ever seen. */
data->text_height = IntMax( data->text_height, height );
text_width_max = IntMax( text_width_max, plinedata->width );
text += plinedata->length + 1;
/* Break if there are no more linefeeds. */
if ( !lf )
break;
}
/* Bump up the text height slightly. */
data->text_height += 2;
}
/* Loop through all buttons and calculate the button widths and height. */
for ( i = 0; i < data->numbuttons; i++ )
{
int height;
data->buttonpos[ i ].buttondata = &data->buttondata[ i ];
data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text );
GetTextWidthHeight( fontinfo, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ),
&data->buttonpos[ i ].text_width, &height );
button_width = IntMax( button_width, data->buttonpos[ i ].text_width );
button_text_height = IntMax( button_text_height, height );
}
if ( data->numlines )
{
/* x,y for this line of text. */
data->xtext = data->text_height;
data->ytext = data->text_height + data->text_height;
/* Bump button y down to bottom of text. */
ybuttons = 3 * data->ytext / 2 + ( data->numlines - 1 ) * data->text_height;
/* Bump the dialog box width and height up if needed. */
data->dialog_width = IntMax( data->dialog_width, 2 * data->xtext + text_width_max );
data->dialog_height = IntMax( data->dialog_height, ybuttons );
}
else
{
/* Button y starts at height of button text. */
ybuttons = button_text_height;
}
if ( data->numbuttons )
{
int x, y;
int width_of_buttons;
int button_spacing = button_text_height;
int button_height = 2 * button_text_height;
/* Bump button width up a bit. */
button_width += button_text_height;
/* Get width of all buttons lined up. */
width_of_buttons = data->numbuttons * button_width + ( data->numbuttons - 1 ) * button_spacing;
/* Bump up dialog width and height if buttons are wider than text. */
data->dialog_width = IntMax( data->dialog_width, width_of_buttons + 2 * button_spacing );
data->dialog_height = IntMax( data->dialog_height, ybuttons + 2 * button_height );
/* Location for first button. */
x = ( data->dialog_width - width_of_buttons ) / 2;
y = ybuttons + ( data->dialog_height - ybuttons - button_height ) / 2;
for ( i = 0; i < data->numbuttons; i++ )
{
/* Button coordinates. */
data->buttonpos[ i ].rect.x = x;
data->buttonpos[ i ].rect.y = y;
data->buttonpos[ i ].rect.w = button_width;
data->buttonpos[ i ].rect.h = button_height;
/* Button text coordinates. */
data->buttonpos[ i ].x = x + ( button_width - data->buttonpos[ i ].text_width ) / 2;
data->buttonpos[ i ].y = y + ( button_height - button_text_height - 1 ) / 2 + button_text_height;
/* Scoot over for next button. */
x += button_width + button_text_height;
}
}
XFreeFontInfo( NULL, fontinfo, 1 );
return 0;
}
/* Free SDL_MessageBoxData data. */
static void
X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data )
{
if ( data->hfont != None )
{
XUnloadFont( data->display, data->hfont );
data->hfont = None;
}
if ( data->display )
{
if ( data->window != None )
{
XUnmapWindow( data->display, data->window );
XDestroyWindow( data->display, data->window );
data->window = None;
}
XCloseDisplay( data->display );
data->display = NULL;
}
}
/* Create and set up our X11 dialog box indow. */
static int
X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data )
{
int x, y;
XSizeHints *sizehints;
XSetWindowAttributes wnd_attr;
Display *display = data->display;
SDL_WindowData *windowdata = NULL;
const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
if ( messageboxdata->window ) {
windowdata = (SDL_WindowData *)messageboxdata->window->driverdata;
}
data->event_mask = ExposureMask |
ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
StructureNotifyMask | FocusChangeMask | PointerMotionMask;
wnd_attr.event_mask = data->event_mask;
data->window = XCreateWindow(
display, DefaultRootWindow( display ),
0, 0,
data->dialog_width, data->dialog_height,
0, CopyFromParent, InputOutput, CopyFromParent,
CWEventMask, &wnd_attr );
if ( data->window == None ) {
SDL_SetError("Couldn't create X window");
return -1;
}
if ( windowdata ) {
/* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */
XSetTransientForHint( display, data->window, windowdata->xwindow );
}
XStoreName( display, data->window, messageboxdata->title );
/* Allow the window to be deleted by the window manager */
data->wm_protocols = XInternAtom( display, "WM_PROTOCOLS", False );
data->wm_delete_message = XInternAtom( display, "WM_DELETE_WINDOW", False );
XSetWMProtocols( display, data->window, &data->wm_delete_message, 1 );
if ( windowdata ) {
XWindowAttributes attrib;
Window dummy;
XGetWindowAttributes(display, windowdata->xwindow, &attrib);
x = attrib.x + ( attrib.width - data->dialog_width ) / 2;
y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ;
XTranslateCoordinates(display, windowdata->xwindow, DefaultRootWindow( display ), x, y, &x, &y, &dummy);
} else {
int screen = DefaultScreen( display );
x = ( DisplayWidth( display, screen ) - data->dialog_width ) / 2;
y = ( DisplayHeight( display, screen ) - data->dialog_height ) / 3 ;
}
XMoveWindow( display, data->window, x, y );
sizehints = XAllocSizeHints();
if ( sizehints ) {
sizehints->flags = USPosition | USSize | PMaxSize | PMinSize;
sizehints->x = x;
sizehints->y = y;
sizehints->width = data->dialog_width;
sizehints->height = data->dialog_height;
sizehints->min_width = sizehints->max_width = data->dialog_width;
sizehints->min_height = sizehints->max_height = data->dialog_height;
XSetWMNormalHints( display, data->window, sizehints );
XFree( sizehints );
}
XMapRaised( display, data->window );
return 0;
}
/* Draw our message box. */
static void
X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx )
{
int i;
Window window = data->window;
Display *display = data->display;
XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ] );
XFillRectangle( display, window, ctx, 0, 0, data->dialog_width, data->dialog_height );
XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
for ( i = 0; i < data->numlines; i++ )
{
TextLineData *plinedata = &data->linedata[ i ];
XDrawString( display, window, ctx,
data->xtext, data->ytext + i * data->text_height,
plinedata->text, plinedata->length );
}
for ( i = 0; i < data->numbuttons; i++ )
{
SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
const SDL_MessageBoxButtonData *buttondata = buttondatax11->buttondata;
int border = ( buttondata->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT ) ? 2 : 0;
int offset = ( ( data->mouse_over_index == i ) && ( data->button_press_index == data->mouse_over_index ) ) ? 1 : 0;
XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND ] );
XFillRectangle( display, window, ctx,
buttondatax11->rect.x - border, buttondatax11->rect.y - border,
buttondatax11->rect.w + 2 * border, buttondatax11->rect.h + 2 * border );
XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BORDER ] );
XDrawRectangle( display, window, ctx,
buttondatax11->rect.x, buttondatax11->rect.y,
buttondatax11->rect.w, buttondatax11->rect.h );
XSetForeground( display, ctx, ( data->mouse_over_index == i ) ?
data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] :
data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
XDrawString( display, window, ctx,
buttondatax11->x + offset, buttondatax11->y + offset,
buttondata->text, buttondatax11->length );
}
}
/* Loop and handle message box event messages until something kills it. */
static int
X11_MessageBoxLoop( SDL_MessageBoxDataX11 *data )
{
GC ctx;
XGCValues ctx_vals;
SDL_bool close_dialog = SDL_FALSE;
SDL_bool has_focus = SDL_TRUE;
KeySym last_key_pressed = XK_VoidSymbol;
ctx_vals.font = data->hfont;
ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
ctx = XCreateGC( data->display, data->window, GCForeground | GCBackground | GCFont, &ctx_vals );
if ( ctx == None ) {
SDL_SetError("Couldn't create graphics context");
return -1;
}
data->button_press_index = -1; /* Reset what button is currently depressed. */
data->mouse_over_index = -1; /* Reset what button the mouse is over. */
while( !close_dialog ) {
XEvent e;
SDL_bool draw = SDL_TRUE;
XWindowEvent( data->display, data->window, data->event_mask, &e );
/* If XFilterEvent returns True, then some input method has filtered the
event, and the client should discard the event. */
if ( ( e.type != Expose ) && XFilterEvent( &e, None ) )
continue;
switch( e.type ) {
case Expose:
if ( e.xexpose.count > 0 ) {
draw = SDL_FALSE;
}
break;
case FocusIn:
/* Got focus. */
has_focus = SDL_TRUE;
break;
case FocusOut:
/* lost focus. Reset button and mouse info. */
has_focus = SDL_FALSE;
data->button_press_index = -1;
data->mouse_over_index = -1;
break;
case MotionNotify:
if ( has_focus ) {
/* Mouse moved... */
data->mouse_over_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
}
break;
case ClientMessage:
if ( e.xclient.message_type == data->wm_protocols &&
e.xclient.format == 32 &&
e.xclient.data.l[ 0 ] == data->wm_delete_message ) {
close_dialog = SDL_TRUE;
}
break;
case KeyPress:
/* Store key press - we make sure in key release that we got both. */
last_key_pressed = XLookupKeysym( &e.xkey, 0 );
break;
case KeyRelease:
{
Uint32 mask = 0;
KeySym key = XLookupKeysym( &e.xkey, 0 );
/* If this is a key release for something we didn't get the key down for, then bail. */
if ( key != last_key_pressed )
break;
if ( key == XK_Escape )
mask = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
else if ( ( key == XK_Return ) || ( key == XK_KP_Enter ) )
mask = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
if ( mask ) {
int i;
/* Look for first button with this mask set, and return it if found. */
for ( i = 0; i < data->numbuttons; i++ ) {
SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
if ( buttondatax11->buttondata->flags & mask ) {
*data->pbuttonid = buttondatax11->buttondata->buttonid;
close_dialog = SDL_TRUE;
break;
}
}
}
break;
}
case ButtonPress:
data->button_press_index = -1;
if ( e.xbutton.button == Button1 ) {
/* Find index of button they clicked on. */
data->button_press_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
}
break;
case ButtonRelease:
/* If button is released over the same button that was clicked down on, then return it. */
if ( ( e.xbutton.button == Button1 ) && ( data->button_press_index >= 0 ) ) {
int button = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
if ( data->button_press_index == button ) {
SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ button ];
*data->pbuttonid = buttondatax11->buttondata->buttonid;
close_dialog = SDL_TRUE;
}
}
data->button_press_index = -1;
break;
}
if ( draw ) {
/* Draw our dialog box. */
X11_MessageBoxDraw( data, ctx );
}
}
XFreeGC( data->display, ctx );
return 0;
}
/* Display an x11 message box. */
int
X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{
int ret;
SDL_MessageBoxDataX11 data;
SDL_memset( &data, 0, sizeof( data ) );
if ( !SDL_X11_LoadSymbols() )
return -1;
/* This code could get called from multiple threads maybe? */
XInitThreads();
/* Initialize the return buttonid value to -1 (for error or dialogbox closed). */
*buttonid = -1;
/* Init and display the message box. */
ret = X11_MessageBoxInit( &data, messageboxdata, buttonid );
if ( ret != -1 ) {
ret = X11_MessageBoxInitPositions( &data );
if ( ret != -1 ) {
ret = X11_MessageBoxCreateWindow( &data );
if ( ret != -1 ) {
ret = X11_MessageBoxLoop( &data );
}
}
}
X11_MessageBoxShutdown( &data );
return ret;
}
#endif /* SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -43,13 +43,17 @@ SDL_X11_SYM(int,XDefineCursor,(Display* a,Window b,Cursor c),(a,b,c),return)
SDL_X11_SYM(int,XDeleteProperty,(Display* a,Window b,Atom c),(a,b,c),return) SDL_X11_SYM(int,XDeleteProperty,(Display* a,Window b,Atom c),(a,b,c),return)
SDL_X11_SYM(int,XDestroyWindow,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XDestroyWindow,(Display* a,Window b),(a,b),return)
SDL_X11_SYM(int,XDisplayKeycodes,(Display* a,int* b,int* c),(a,b,c),return) SDL_X11_SYM(int,XDisplayKeycodes,(Display* a,int* b,int* c),(a,b,c),return)
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)
SDL_X11_SYM(char*,XDisplayName,(_Xconst char* a),(a),return) SDL_X11_SYM(char*,XDisplayName,(_Xconst char* a),(a),return)
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)
SDL_X11_SYM(int,XEventsQueued,(Display* a,int b),(a,b),return) SDL_X11_SYM(int,XEventsQueued,(Display* a,int b),(a,b),return)
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)
SDL_X11_SYM(Bool,XFilterEvent,(XEvent *event,Window w),(event,w),return) SDL_X11_SYM(Bool,XFilterEvent,(XEvent *event,Window w),(event,w),return)
SDL_X11_SYM(int,XFlush,(Display* a),(a),return) SDL_X11_SYM(int,XFlush,(Display* a),(a),return)
SDL_X11_SYM(int,XFree,(void*a),(a),return) SDL_X11_SYM(int,XFree,(void*a),(a),return)
SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return) SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return)
SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return) SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return)
SDL_X11_SYM(int,XFreeFontInfo,(char** a,XFontStruct* b,int c),(a,b,c),return)
SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return) SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return)
SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return) SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return)
SDL_X11_SYM(char*,XGetAtomName,(Display *a,Atom b),(a,b),return) SDL_X11_SYM(char*,XGetAtomName,(Display *a,Atom b),(a,b),return)
@ -73,6 +77,7 @@ SDL_X11_SYM(char*,XKeysymToString,(KeySym a),(a),return)
SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return) SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return)
SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return) SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return)
SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return) SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return)
SDL_X11_SYM(Font,XLoadFont,(Display* a,_Xconst char* b),(a,b),return)
SDL_X11_SYM(KeySym,XLookupKeysym,(XKeyEvent* a,int b),(a,b),return) SDL_X11_SYM(KeySym,XLookupKeysym,(XKeyEvent* a,int b),(a,b),return)
SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return) SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return)
SDL_X11_SYM(int,XMapRaised,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XMapRaised,(Display* a,Window b),(a,b),return)
@ -85,6 +90,7 @@ SDL_X11_SYM(Status,XInitThreads,(void),(),return)
SDL_X11_SYM(int,XPeekEvent,(Display* a,XEvent* b),(a,b),return) SDL_X11_SYM(int,XPeekEvent,(Display* a,XEvent* b),(a,b),return)
SDL_X11_SYM(int,XPending,(Display* a),(a),return) SDL_X11_SYM(int,XPending,(Display* a),(a),return)
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) 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)
SDL_X11_SYM(XFontStruct*,XQueryFont,(Display* a,XID b),(a,b),return)
SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return) SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return)
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) 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)
SDL_X11_SYM(int,XRaiseWindow,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XRaiseWindow,(Display* a,Window b),(a,b),return)
@ -94,6 +100,7 @@ SDL_X11_SYM(int,XResizeWindow,(Display* a,Window b,unsigned int c,unsigned int d
SDL_X11_SYM(int,XSelectInput,(Display* a,Window b,long c),(a,b,c),return) SDL_X11_SYM(int,XSelectInput,(Display* a,Window b,long c),(a,b,c),return)
SDL_X11_SYM(Status,XSendEvent,(Display* a,Window b,Bool c,long d,XEvent* e),(a,b,c,d,e),return) SDL_X11_SYM(Status,XSendEvent,(Display* a,Window b,Bool c,long d,XEvent* e),(a,b,c,d,e),return)
SDL_X11_SYM(XErrorHandler,XSetErrorHandler,(XErrorHandler a),(a),return) SDL_X11_SYM(XErrorHandler,XSetErrorHandler,(XErrorHandler a),(a),return)
SDL_X11_SYM(int,XSetForeground,(Display* a,GC b,unsigned long c),(a,b,c),return)
SDL_X11_SYM(XIOErrorHandler,XSetIOErrorHandler,(XIOErrorHandler a),(a),return) SDL_X11_SYM(XIOErrorHandler,XSetIOErrorHandler,(XIOErrorHandler a),(a),return)
SDL_X11_SYM(int,XSetInputFocus,(Display *a,Window b,int c,Time d),(a,b,c,d),return) SDL_X11_SYM(int,XSetInputFocus,(Display *a,Window b,int c,Time d),(a,b,c,d),return)
SDL_X11_SYM(int,XSetSelectionOwner,(Display* a,Atom b,Window c,Time d),(a,b,c,d),return) SDL_X11_SYM(int,XSetSelectionOwner,(Display* a,Atom b,Window c,Time d),(a,b,c,d),return)
@ -104,15 +111,20 @@ SDL_X11_SYM(void,XSetWMProperties,(Display* a,Window b,XTextProperty* c,XTextPro
SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),) SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),)
SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return) SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return)
SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return) SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return)
SDL_X11_SYM(int,XStoreName,(Display* a,Window b,_Xconst char* c),(a,b,c),return)
SDL_X11_SYM(Status,XStringListToTextProperty,(char** a,int b,XTextProperty* c),(a,b,c),return) SDL_X11_SYM(Status,XStringListToTextProperty,(char** a,int b,XTextProperty* c),(a,b,c),return)
SDL_X11_SYM(int,XSync,(Display* a,Bool b),(a,b),return) SDL_X11_SYM(int,XSync,(Display* a,Bool b),(a,b),return)
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)
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)
SDL_X11_SYM(int,XUndefineCursor,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XUndefineCursor,(Display* a,Window b),(a,b),return)
SDL_X11_SYM(int,XUngrabKeyboard,(Display* a,Time b),(a,b),return) SDL_X11_SYM(int,XUngrabKeyboard,(Display* a,Time b),(a,b),return)
SDL_X11_SYM(int,XUngrabPointer,(Display* a,Time b),(a,b),return) SDL_X11_SYM(int,XUngrabPointer,(Display* a,Time b),(a,b),return)
SDL_X11_SYM(int,XUngrabServer,(Display* a),(a),return) SDL_X11_SYM(int,XUngrabServer,(Display* a),(a),return)
SDL_X11_SYM(int,XUninstallColormap,(Display* a,Colormap b),(a,b),return) SDL_X11_SYM(int,XUninstallColormap,(Display* a,Colormap b),(a,b),return)
SDL_X11_SYM(int,XUnloadFont,(Display* a,Font b),(a,b),return)
SDL_X11_SYM(int,XUnmapWindow,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XUnmapWindow,(Display* a,Window b),(a,b),return)
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) 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)
SDL_X11_SYM(int,XWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return)
SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return) SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return)
#if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY #if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY
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) 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)

View file

@ -1204,6 +1204,12 @@ CommonEvent(CommonState * state, SDL_Event * event, int *done)
} }
} }
break; break;
case SDLK_1:
if (event->key.keysym.mod & KMOD_CTRL) {
SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Test Message", "You're awesome!", window);
}
break;
case SDLK_ESCAPE: case SDLK_ESCAPE:
*done = 1; *done = 1;
break; break;