From 62d8685ff514a8c6d654315849cf9d668838a0a4 Mon Sep 17 00:00:00 2001 From: Michael Sartain Date: Mon, 19 Nov 2012 15:11:10 -0800 Subject: [PATCH] Add SDL_CreateSystemCursor for Windows and Linux. --- include/SDL_mouse.h | 25 ++++++++++++++++ src/events/SDL_mouse.c | 20 +++++++++++++ src/events/SDL_mouse_c.h | 3 ++ src/video/windows/SDL_windowsmouse.c | 40 ++++++++++++++++++++++++++ src/video/x11/SDL_x11mouse.c | 43 ++++++++++++++++++++++++++++ src/video/x11/SDL_x11sym.h | 1 + 6 files changed, 132 insertions(+) diff --git a/include/SDL_mouse.h b/include/SDL_mouse.h index af2774ab6..8bf1f61ac 100644 --- a/include/SDL_mouse.h +++ b/include/SDL_mouse.h @@ -58,6 +58,24 @@ extern "C" { typedef struct SDL_Cursor SDL_Cursor; /* Implementation dependent */ +/** + * \brief Cursor types for SDL_CreateSystemCursor. + */ +typedef enum +{ + SDL_SYSTEM_CURSOR_ARROW, // Arrow + SDL_SYSTEM_CURSOR_IBEAM, // I-beam + SDL_SYSTEM_CURSOR_WAIT, // Wait + SDL_SYSTEM_CURSOR_CROSSHAIR, // Crosshair + SDL_SYSTEM_CURSOR_WAITARROW, // Small wait cursor (or Wait if not available) + SDL_SYSTEM_CURSOR_SIZENWSE, // Double arrow pointing northwest and southeast + SDL_SYSTEM_CURSOR_SIZENESW, // Double arrow pointing northeast and southwest + SDL_SYSTEM_CURSOR_SIZEWE, // Double arrow pointing west and east + SDL_SYSTEM_CURSOR_SIZENS, // Double arrow pointing north and south + SDL_SYSTEM_CURSOR_SIZEALL, // Four pointed arrow pointing north, south, east, and west + SDL_SYSTEM_CURSOR_NO, // Slashed circle or crossbones + SDL_SYSTEM_CURSOR_HAND, // Hand +} SDL_SystemCursor; /* Function prototypes */ @@ -154,6 +172,13 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y); +/** + * \brief Create a system cursor. + * + * \sa SDL_FreeCursor() + */ +extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateSystemCursor(SDL_SystemCursor id); + /** * \brief Set the active cursor. */ diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 2d20a448c..a61f21520 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -528,6 +528,26 @@ SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y) return cursor; } +SDL_Cursor * +SDL_CreateSystemCursor(SDL_SystemCursor id) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_Cursor *cursor; + + if (!mouse->CreateSystemCursor) { + SDL_SetError("CreateSystemCursor is not currently supported"); + return NULL; + } + + cursor = mouse->CreateSystemCursor(id); + if (cursor) { + cursor->next = mouse->cursors; + mouse->cursors = cursor; + } + + return cursor; +} + /* SDL_SetCursor(NULL) can be used to force the cursor redraw, if this is desired for any reason. This is used when setting the video mode and when the SDL window gains the mouse focus. diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index cf99a86ac..4918aea98 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -36,6 +36,9 @@ typedef struct /* Create a cursor from a surface */ SDL_Cursor *(*CreateCursor) (SDL_Surface * surface, int hot_x, int hot_y); + /* Create a system cursor */ + SDL_Cursor *(*CreateSystemCursor) (SDL_SystemCursor id); + /* Show the specified cursor, or hide if cursor is NULL */ int (*ShowCursor) (SDL_Cursor * cursor); diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index d0d30b945..3b3b95f85 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -102,6 +102,45 @@ WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) return cursor; } +static SDL_Cursor * +WIN_CreateSystemCursor(SDL_SystemCursor id) +{ + SDL_Cursor *cursor; + LPCTSTR name; + + switch(id) + { + default: + SDL_assert(0); + return NULL; + case SDL_SYSTEM_CURSOR_ARROW: name = IDC_ARROW; break; + case SDL_SYSTEM_CURSOR_IBEAM: name = IDC_IBEAM; break; + case SDL_SYSTEM_CURSOR_WAIT: name = IDC_WAIT; break; + case SDL_SYSTEM_CURSOR_CROSSHAIR: name = IDC_CROSS; break; + case SDL_SYSTEM_CURSOR_WAITARROW: name = IDC_WAIT; break; + case SDL_SYSTEM_CURSOR_SIZENWSE: name = IDC_SIZENWSE; break; + case SDL_SYSTEM_CURSOR_SIZENESW: name = IDC_SIZENESW; break; + case SDL_SYSTEM_CURSOR_SIZEWE: name = IDC_SIZEWE; break; + case SDL_SYSTEM_CURSOR_SIZENS: name = IDC_SIZENS; break; + case SDL_SYSTEM_CURSOR_SIZEALL: name = IDC_SIZEALL; break; + case SDL_SYSTEM_CURSOR_NO: name = IDC_NO; break; + case SDL_SYSTEM_CURSOR_HAND: name = IDC_HAND; break; + } + + cursor = SDL_calloc(1, sizeof(*cursor)); + if (cursor) { + HICON hicon; + + hicon = LoadCursor(NULL, name); + + cursor->driverdata = hicon; + } else { + SDL_OutOfMemory(); + } + + return cursor; +} + static void WIN_FreeCursor(SDL_Cursor * cursor) { @@ -190,6 +229,7 @@ WIN_InitMouse(_THIS) SDL_Mouse *mouse = SDL_GetMouse(); mouse->CreateCursor = WIN_CreateCursor; + mouse->CreateSystemCursor = WIN_CreateSystemCursor; mouse->ShowCursor = WIN_ShowCursor; mouse->FreeCursor = WIN_FreeCursor; mouse->WarpMouse = WIN_WarpMouse; diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index d9454bd8a..40ac0c211 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -22,6 +22,7 @@ #if SDL_VIDEO_DRIVER_X11 +#include #include "SDL_assert.h" #include "SDL_x11video.h" #include "SDL_x11mouse.h" @@ -218,6 +219,47 @@ X11_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) return cursor; } +static SDL_Cursor * +X11_CreateSystemCursor(SDL_SystemCursor id) +{ + SDL_Cursor *cursor; + unsigned int shape; + + switch(id) + { + default: + SDL_assert(0); + return NULL; + // X Font Cursors reference: + // http://tronche.com/gui/x/xlib/appendix/b/ + case SDL_SYSTEM_CURSOR_ARROW: shape = XC_arrow; break; + case SDL_SYSTEM_CURSOR_IBEAM: shape = XC_xterm; break; + case SDL_SYSTEM_CURSOR_WAIT: shape = XC_watch; break; + case SDL_SYSTEM_CURSOR_CROSSHAIR: shape = XC_tcross; break; + case SDL_SYSTEM_CURSOR_WAITARROW: shape = XC_watch; break; + case SDL_SYSTEM_CURSOR_SIZENWSE: shape = XC_fleur; break; + case SDL_SYSTEM_CURSOR_SIZENESW: shape = XC_fleur; break; + case SDL_SYSTEM_CURSOR_SIZEWE: shape = XC_sb_h_double_arrow; break; + case SDL_SYSTEM_CURSOR_SIZENS: shape = XC_sb_v_double_arrow; break; + case SDL_SYSTEM_CURSOR_SIZEALL: shape = XC_fleur; break; + case SDL_SYSTEM_CURSOR_NO: shape = XC_pirate; break; + case SDL_SYSTEM_CURSOR_HAND: shape = XC_hand2; break; + } + + cursor = SDL_calloc(1, sizeof(*cursor)); + if (cursor) { + Cursor x11_cursor; + + x11_cursor = XCreateFontCursor(GetDisplay(), shape); + + cursor->driverdata = (void*)x11_cursor; + } else { + SDL_OutOfMemory(); + } + + return cursor; +} + static void X11_FreeCursor(SDL_Cursor * cursor) { @@ -288,6 +330,7 @@ X11_InitMouse(_THIS) SDL_Mouse *mouse = SDL_GetMouse(); mouse->CreateCursor = X11_CreateCursor; + mouse->CreateSystemCursor = X11_CreateSystemCursor; mouse->ShowCursor = X11_ShowCursor; mouse->FreeCursor = X11_FreeCursor; mouse->WarpMouse = X11_WarpMouse; diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index c7cc2a966..394a39707 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -36,6 +36,7 @@ SDL_X11_SYM(int,XConvertSelection,(Display* a,Atom b,Atom c,Atom d,Window e,Time SDL_X11_SYM(Pixmap,XCreateBitmapFromData,(Display *dpy,Drawable d,_Xconst char *data,unsigned int width,unsigned int height),(dpy,d,data,width,height),return) SDL_X11_SYM(Colormap,XCreateColormap,(Display* a,Window b,Visual* c,int d),(a,b,c,d),return) SDL_X11_SYM(Cursor,XCreatePixmapCursor,(Display* a,Pixmap b,Pixmap c,XColor* d,XColor* e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return) +SDL_X11_SYM(Cursor,XCreateFontCursor,(Display* a,unsigned int b),(a,b),return) SDL_X11_SYM(GC,XCreateGC,(Display* a,Drawable b,unsigned long c,XGCValues* d),(a,b,c,d),return) SDL_X11_SYM(XImage*,XCreateImage,(Display* a,Visual* b,unsigned int c,int d,int e,char* f,unsigned int g,unsigned int h,int i,int j),(a,b,c,d,e,f,g,h,i,j),return) SDL_X11_SYM(Window,XCreateWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,int h,unsigned int i,Visual* j,unsigned long k,XSetWindowAttributes* l),(a,b,c,d,e,f,g,h,i,j,k,l),return)