From c2cf5fd0488e5c65d00ba93c854c352a8491803e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 28 Feb 2011 23:50:32 -0800 Subject: [PATCH] Added support for Windows cursors --- VisualC/SDL_VS2008.sln | 13 + VisualC/SDL_VS2010.sln | 13 +- .../tests/testcursor/testcursor_VS2005.vcproj | 239 ++++++++++++++++++ .../tests/testcursor/testcursor_VS2008.vcproj | 217 ++++++++++++++++ .../testcursor/testcursor_VS2010.vcxproj | 157 ++++++++++++ src/video/windows/SDL_windowsevents.c | 7 +- src/video/windows/SDL_windowsmouse.c | 132 ++++++++++ src/video/windows/SDL_windowsmouse.h | 2 + 8 files changed, 772 insertions(+), 8 deletions(-) mode change 100644 => 100755 VisualC/SDL_VS2008.sln create mode 100755 VisualC/tests/testcursor/testcursor_VS2005.vcproj create mode 100755 VisualC/tests/testcursor/testcursor_VS2008.vcproj create mode 100755 VisualC/tests/testcursor/testcursor_VS2010.vcxproj diff --git a/VisualC/SDL_VS2008.sln b/VisualC/SDL_VS2008.sln old mode 100644 new mode 100755 index ce22066ea..b55914a1f --- a/VisualC/SDL_VS2008.sln +++ b/VisualC/SDL_VS2008.sln @@ -144,6 +144,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testatomic", "tests\testato {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A} = {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testcursor", "tests\testcursor\testcursor_VS2008.vcproj", "{39B2FE52-578B-4C92-944E-50F50C581683}" + ProjectSection(ProjectDependencies) = postProject + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68} = {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68} + {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A} = {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -306,6 +312,12 @@ Global {66B32F7E-5716-48D0-B5B9-D832FD052DD5}.Release|Win32.ActiveCfg = Release|Win32 {66B32F7E-5716-48D0-B5B9-D832FD052DD5}.Release|Win32.Build.0 = Release|Win32 {66B32F7E-5716-48D0-B5B9-D832FD052DD5}.Release|x64.ActiveCfg = Release|Win32 + {39B2FE52-578B-4C92-944E-50F50C581683}.Debug|Win32.ActiveCfg = Debug|Win32 + {39B2FE52-578B-4C92-944E-50F50C581683}.Debug|Win32.Build.0 = Debug|Win32 + {39B2FE52-578B-4C92-944E-50F50C581683}.Debug|x64.ActiveCfg = Debug|Win32 + {39B2FE52-578B-4C92-944E-50F50C581683}.Release|Win32.ActiveCfg = Release|Win32 + {39B2FE52-578B-4C92-944E-50F50C581683}.Release|Win32.Build.0 = Release|Win32 + {39B2FE52-578B-4C92-944E-50F50C581683}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -334,5 +346,6 @@ Global {31A3E4E1-AAE9-4EF3-9B23-18D0924BE4D2} = {CE748C1F-3C21-4825-AA6A-F895A023F7E7} {79CEE57E-1BC3-4FF6-90B3-9E39763CDAFF} = {CE748C1F-3C21-4825-AA6A-F895A023F7E7} {66B32F7E-5716-48D0-B5B9-D832FD052DD5} = {CE748C1F-3C21-4825-AA6A-F895A023F7E7} + {39B2FE52-578B-4C92-944E-50F50C581683} = {CE748C1F-3C21-4825-AA6A-F895A023F7E7} EndGlobalSection EndGlobal diff --git a/VisualC/SDL_VS2010.sln b/VisualC/SDL_VS2010.sln index 4dc8d3684..1764ed2ed 100644 --- a/VisualC/SDL_VS2010.sln +++ b/VisualC/SDL_VS2010.sln @@ -133,6 +133,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testpower", "tests\testpowe {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A} = {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testcursor", "tests\testcursor\testcursor_VS2010.vcxproj", "{20839E82-6F23-429D-91D7-8A2601BC7EA8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -151,8 +153,8 @@ Global {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x64.Build.0 = Release|x64 {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|Win32.ActiveCfg = Debug|Win32 {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|Win32.Build.0 = Debug|Win32 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|x64.ActiveCfg = Debug|x64 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|x64.Build.0 = Debug|x64 + {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|x64.ActiveCfg = Debug|Win32 + {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|x64.Build.0 = Debug|Win32 {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|Win32.ActiveCfg = Release|Win32 {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|Win32.Build.0 = Release|Win32 {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|x64.ActiveCfg = Release|x64 @@ -282,6 +284,12 @@ Global {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Release|Win32.ActiveCfg = Release|Win32 {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Release|Win32.Build.0 = Release|Win32 {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Release|x64.ActiveCfg = Release|Win32 + {20839E82-6F23-429D-91D7-8A2601BC7EA8}.Debug|Win32.ActiveCfg = Debug|Win32 + {20839E82-6F23-429D-91D7-8A2601BC7EA8}.Debug|Win32.Build.0 = Debug|Win32 + {20839E82-6F23-429D-91D7-8A2601BC7EA8}.Debug|x64.ActiveCfg = Debug|Win32 + {20839E82-6F23-429D-91D7-8A2601BC7EA8}.Release|Win32.ActiveCfg = Release|Win32 + {20839E82-6F23-429D-91D7-8A2601BC7EA8}.Release|Win32.Build.0 = Release|Win32 + {20839E82-6F23-429D-91D7-8A2601BC7EA8}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -308,5 +316,6 @@ Global {EDEA9D00-AF64-45DE-8F60-5957048F2F0F} = {CE748C1F-3C21-4825-AA6A-F895A023F7E7} {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF} = {CE748C1F-3C21-4825-AA6A-F895A023F7E7} {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3} = {CE748C1F-3C21-4825-AA6A-F895A023F7E7} + {20839E82-6F23-429D-91D7-8A2601BC7EA8} = {CE748C1F-3C21-4825-AA6A-F895A023F7E7} EndGlobalSection EndGlobal diff --git a/VisualC/tests/testcursor/testcursor_VS2005.vcproj b/VisualC/tests/testcursor/testcursor_VS2005.vcproj new file mode 100755 index 000000000..b6281dbd0 --- /dev/null +++ b/VisualC/tests/testcursor/testcursor_VS2005.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/VisualC/tests/testcursor/testcursor_VS2008.vcproj b/VisualC/tests/testcursor/testcursor_VS2008.vcproj new file mode 100755 index 000000000..7e8326b0b --- /dev/null +++ b/VisualC/tests/testcursor/testcursor_VS2008.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/VisualC/tests/testcursor/testcursor_VS2010.vcxproj b/VisualC/tests/testcursor/testcursor_VS2010.vcxproj new file mode 100755 index 000000000..ac0cc7dd8 --- /dev/null +++ b/VisualC/tests/testcursor/testcursor_VS2010.vcxproj @@ -0,0 +1,157 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + testcursor + testcursor + {20839E82-6F23-429D-91D7-8A2601BC7EA8} + + + + Application + false + + + Application + false + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/testcursor.tlb + + + + + Disabled + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreadedDebugDLL + .\Debug/testcursor.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + .\Debug/testcursor.exe + true + true + .\Debug/testcursor.pdb + Windows + MachineX86 + + + true + .\Debug/testcursor.bsc + + + copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll + + + Copy SDL + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/testcursor.tlb + + + + + MaxSpeed + OnlyExplicitInline + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + .\Release/testcursor.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + .\Release/testcursor.exe + true + .\Release/testcursor.pdb + Windows + MachineX86 + + + true + .\Release/testcursor.bsc + + + copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll + + + Copy SDL + + + + + + + + + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + + + + \ No newline at end of file diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index ea28a16f5..9cb7bb1eb 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -490,12 +490,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) hittest = LOWORD(lParam); if (hittest == HTCLIENT) { - /* FIXME: Implement the cursor API */ - static HCURSOR cursor; - if (!cursor) { - cursor = LoadCursor(NULL, IDC_ARROW); - } - SetCursor(cursor); + SetCursor(SDL_cursor); returnCode = TRUE; } } diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index efb243b6b..08e88a065 100755 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -24,9 +24,141 @@ #include "SDL_windowsvideo.h" +#include "../../events/SDL_mouse_c.h" + + +HCURSOR SDL_cursor = NULL; + + +static SDL_Cursor * +WIN_CreateDefaultCursor() +{ + SDL_Cursor *cursor; + + cursor = SDL_calloc(1, sizeof(*cursor)); + if (cursor) { + cursor->driverdata = LoadCursor(NULL, IDC_ARROW); + } else { + SDL_OutOfMemory(); + } + + return cursor; +} + +static SDL_Cursor * +WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) +{ + SDL_Cursor *cursor; + SDL_Surface *cvt; + HICON hicon; + HDC hdc; + BITMAPV4HEADER bmh; + LPVOID pixels; + ICONINFO ii; + + SDL_zero(bmh); + bmh.bV4Size = sizeof(bmh); + bmh.bV4Width = surface->w; + bmh.bV4Height = -surface->h; /* Invert the image */ + bmh.bV4Planes = 1; + bmh.bV4BitCount = 32; + bmh.bV4V4Compression = BI_BITFIELDS; + bmh.bV4AlphaMask = 0xFF000000; + bmh.bV4RedMask = 0x00FF0000; + bmh.bV4GreenMask = 0x0000FF00; + bmh.bV4BlueMask = 0x000000FF; + + hdc = GetDC(NULL); + SDL_zero(ii); + ii.fIcon = FALSE; + ii.xHotspot = (DWORD)hot_x; + ii.yHotspot = (DWORD)hot_y; + ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0); + ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, NULL); + ReleaseDC(NULL, hdc); + + cvt = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0); + if (!cvt) { + return NULL; + } + SDL_memcpy(pixels, cvt->pixels, cvt->h * cvt->pitch); + SDL_FreeSurface(cvt); + + hicon = CreateIconIndirect(&ii); + + DeleteObject(ii.hbmColor); + DeleteObject(ii.hbmMask); + + if (!hicon) { + WIN_SetError("CreateIconIndirect()"); + return NULL; + } + + cursor = SDL_calloc(1, sizeof(*cursor)); + if (cursor) { + cursor->driverdata = hicon; + } else { + DestroyIcon(hicon); + SDL_OutOfMemory(); + } + + return cursor; +} + +static void +WIN_FreeCursor(SDL_Cursor * cursor) +{ + HICON hicon = (HICON)cursor->driverdata; + + DestroyIcon(hicon); + SDL_free(cursor); +} + +static int +WIN_ShowCursor(SDL_Cursor * cursor) +{ + if (cursor) { + SDL_cursor = (HCURSOR)cursor->driverdata; + } else { + SDL_cursor = NULL; + } + if (SDL_GetMouseFocus() != NULL) { + SetCursor(SDL_cursor); + } + return 0; +} + +static void +WIN_WarpMouse(SDL_Window * window, int x, int y) +{ + HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + POINT pt; + + pt.x = x; + pt.y = y; + ClientToScreen(hwnd, &pt); + SetCursorPos(pt.x, pt.y); +} + +static int +WIN_SetRelativeMouseMode(SDL_bool enabled) +{ + SDL_Unsupported(); + return -1; +} + void WIN_InitMouse(_THIS) { + SDL_Mouse *mouse = SDL_GetMouse(); + + mouse->CreateCursor = WIN_CreateCursor; + mouse->ShowCursor = WIN_ShowCursor; + mouse->FreeCursor = WIN_FreeCursor; + mouse->WarpMouse = WIN_WarpMouse; + mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode; + + SDL_SetDefaultCursor(WIN_CreateDefaultCursor()); } void diff --git a/src/video/windows/SDL_windowsmouse.h b/src/video/windows/SDL_windowsmouse.h index 4d1d09108..94205c58c 100644 --- a/src/video/windows/SDL_windowsmouse.h +++ b/src/video/windows/SDL_windowsmouse.h @@ -24,6 +24,8 @@ #ifndef _SDL_windowsmouse_h #define _SDL_windowsmouse_h +extern HCURSOR SDL_cursor; + extern void WIN_InitMouse(_THIS); extern void WIN_QuitMouse(_THIS);