mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-12-15 04:29:37 +00:00
Redo mouse cursor handling
This commit is contained in:
@@ -82,6 +82,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="GpBWCursor_Win32.cpp" />
|
||||
<ClCompile Include="GpColorCursor_Win32.cpp" />
|
||||
<ClCompile Include="GpFiber_Win32.cpp" />
|
||||
<ClCompile Include="GpFileStream_Win32.cpp" />
|
||||
@@ -106,10 +107,10 @@
|
||||
<ClInclude Include="..\GpCommon\IGpDisplayDriverSurface.h" />
|
||||
<ClInclude Include="..\GpCommon\IGpLogDriver.h" />
|
||||
<ClInclude Include="..\GpCommon\IGpPrefsHandler.h" />
|
||||
<ClInclude Include="GpBWCursor_Win32.h" />
|
||||
<ClInclude Include="GpFiber_Win32.h" />
|
||||
<ClInclude Include="GpFileStream_Win32.h" />
|
||||
<ClInclude Include="GpFileSystem_Win32.h" />
|
||||
<ClInclude Include="GpFontHandler_FreeType2.h" />
|
||||
<ClInclude Include="GpLogDriver_Win32.h" />
|
||||
<ClInclude Include="GpMutex_Win32.h" />
|
||||
<ClInclude Include="GpSystemServices_Win32.h" />
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
<ClCompile Include="GpLogDriver_Win32.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GpBWCursor_Win32.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\GpCommon\EGpInputDriverType.h">
|
||||
@@ -57,9 +60,6 @@
|
||||
<ClInclude Include="GpFileSystem_Win32.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GpFontHandler_FreeType2.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\GpCommon\GpInputDriverProperties.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -96,6 +96,9 @@
|
||||
<ClInclude Include="..\GpCommon\GpBuildVersion.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GpBWCursor_Win32.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="ConvertedResources\Large128.ico">
|
||||
|
||||
110
Aerofoil/GpBWCursor_Win32.cpp
Normal file
110
Aerofoil/GpBWCursor_Win32.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Portions of this file based on Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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 "GpBWCursor_Win32.h"
|
||||
#include "GpWindows.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
|
||||
extern GpWindowsGlobals g_gpWindowsGlobals;
|
||||
|
||||
void GpBWCursor_Win32::Destroy()
|
||||
{
|
||||
this->DecRef();
|
||||
}
|
||||
|
||||
IGpCursor_Win32 *GpBWCursor_Win32::Create(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY)
|
||||
{
|
||||
size_t numBits = width * height;
|
||||
size_t numBytes = (width * height + 7) / 8;
|
||||
uint8_t *convertedAndData = static_cast<uint8_t*>(malloc(numBytes));
|
||||
uint8_t *convertedXorData = static_cast<uint8_t*>(malloc(numBytes));
|
||||
|
||||
if (!convertedAndData || !convertedXorData)
|
||||
{
|
||||
if (convertedAndData)
|
||||
free(convertedAndData);
|
||||
if (convertedXorData)
|
||||
free(convertedXorData);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numBytes; i++)
|
||||
{
|
||||
// MacPx0 MacPx1
|
||||
// MacMask0 1a 0x 1a 1x
|
||||
// MacMask1 0a 1x 0a 0x
|
||||
convertedAndData[i] = static_cast<const uint8_t*>(maskData)[i] ^ 0xff;
|
||||
convertedXorData[i] = static_cast<const uint8_t*>(maskData)[i] ^ static_cast<const uint8_t*>(pixelData)[i];
|
||||
}
|
||||
|
||||
HCURSOR hcursor = CreateCursor(g_gpWindowsGlobals.m_hInstance, static_cast<int>(hotSpotX), static_cast<int>(hotSpotY), static_cast<int>(width), static_cast<int>(height), convertedAndData, convertedXorData);
|
||||
|
||||
free(convertedAndData);
|
||||
free(convertedXorData);
|
||||
|
||||
if (!hcursor)
|
||||
return nullptr;
|
||||
|
||||
void *storage = malloc(sizeof(GpBWCursor_Win32));
|
||||
if (!storage)
|
||||
{
|
||||
DestroyCursor(hcursor);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new (storage) GpBWCursor_Win32(hcursor);
|
||||
}
|
||||
|
||||
GpBWCursor_Win32::GpBWCursor_Win32(HCURSOR cursor)
|
||||
: m_cursor(cursor)
|
||||
, m_refCount(1)
|
||||
{
|
||||
}
|
||||
|
||||
GpBWCursor_Win32::~GpBWCursor_Win32()
|
||||
{
|
||||
DestroyCursor(m_cursor);
|
||||
}
|
||||
|
||||
const HCURSOR &GpBWCursor_Win32::GetHCursor() const
|
||||
{
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
void GpBWCursor_Win32::IncRef()
|
||||
{
|
||||
m_refCount++;
|
||||
}
|
||||
|
||||
void GpBWCursor_Win32::DecRef()
|
||||
{
|
||||
m_refCount--;
|
||||
if (m_refCount == 0)
|
||||
{
|
||||
this->~GpBWCursor_Win32();
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
24
Aerofoil/GpBWCursor_Win32.h
Normal file
24
Aerofoil/GpBWCursor_Win32.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "IGpCursor_Win32.h"
|
||||
#include "GpWindows.h"
|
||||
|
||||
class GpBWCursor_Win32 final : public IGpCursor_Win32
|
||||
{
|
||||
public:
|
||||
void Destroy() override;
|
||||
|
||||
const HCURSOR &GetHCursor() const override;
|
||||
|
||||
void IncRef() override;
|
||||
void DecRef() override;
|
||||
|
||||
static IGpCursor_Win32 *Create(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY);
|
||||
|
||||
private:
|
||||
GpBWCursor_Win32(HCURSOR cursor);
|
||||
~GpBWCursor_Win32();
|
||||
|
||||
HCURSOR m_cursor;
|
||||
int m_refCount;
|
||||
};
|
||||
@@ -1,58 +1,132 @@
|
||||
#include "GpCursor_Win32.h"
|
||||
/*
|
||||
Portions of this file based on Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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 "GpColorCursor_Win32.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
|
||||
void GpCursor_Win32::Destroy()
|
||||
void GpColorCursor_Win32::Destroy()
|
||||
{
|
||||
this->DecRef();
|
||||
}
|
||||
|
||||
IGpCursor_Win32 *GpCursor_Win32::Load(const wchar_t *path)
|
||||
IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY)
|
||||
{
|
||||
HANDLE imageH = LoadImageW(nullptr, path, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
|
||||
const size_t paddingBits = (sizeof(void*) * 8);
|
||||
|
||||
if (imageH == nullptr)
|
||||
BITMAPV4HEADER bmp;
|
||||
|
||||
memset(&bmp, 0, sizeof(bmp));
|
||||
bmp.bV4Size = sizeof(bmp);
|
||||
bmp.bV4Width = width;
|
||||
bmp.bV4Height = -static_cast<LONG>(height);
|
||||
bmp.bV4Planes = 1;
|
||||
bmp.bV4BitCount = 32;
|
||||
bmp.bV4V4Compression = BI_BITFIELDS;
|
||||
bmp.bV4AlphaMask = 0xFF000000;
|
||||
bmp.bV4RedMask = 0x00FF0000;
|
||||
bmp.bV4GreenMask = 0x0000FF00;
|
||||
bmp.bV4BlueMask = 0x000000FF;
|
||||
|
||||
size_t maskPitch = width + paddingBits - 1;
|
||||
maskPitch -= maskPitch % paddingBits;
|
||||
|
||||
LPVOID maskBits = malloc(maskPitch * height);
|
||||
if (!maskBits)
|
||||
return nullptr;
|
||||
|
||||
HCURSOR cursor = reinterpret_cast<HCURSOR>(imageH);
|
||||
void *storage = malloc(sizeof(GpCursor_Win32));
|
||||
memset(maskBits, 0xff, maskPitch * height);
|
||||
|
||||
HDC hdc = GetDC(NULL);
|
||||
|
||||
LPVOID pixels;
|
||||
|
||||
ICONINFO ii;
|
||||
memset(&ii, 0, sizeof(ii));
|
||||
ii.fIcon = FALSE;
|
||||
ii.xHotspot = (DWORD)hotSpotX;
|
||||
ii.yHotspot = (DWORD)hotSpotY;
|
||||
ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmp, DIB_RGB_COLORS, &pixels, NULL, 0);
|
||||
ii.hbmMask = CreateBitmap(width, height, 1, 1, maskBits);
|
||||
ReleaseDC(NULL, hdc);
|
||||
|
||||
size_t cursorPitch = width * 4;
|
||||
|
||||
size_t numPixels = width * height;
|
||||
memcpy(pixels, pixelDataRGBA, numPixels * 4);
|
||||
|
||||
for (size_t i = 0; i < numPixels; i++)
|
||||
{
|
||||
uint8_t *pixel = static_cast<uint8_t*>(pixels) + i * 4;
|
||||
std::swap(pixel[0], pixel[2]);
|
||||
}
|
||||
|
||||
HICON hicon = CreateIconIndirect(&ii);
|
||||
|
||||
DeleteObject(ii.hbmColor);
|
||||
DeleteObject(ii.hbmMask);
|
||||
|
||||
if (!hicon)
|
||||
return nullptr;
|
||||
|
||||
void *storage = malloc(sizeof(GpColorCursor_Win32));
|
||||
if (!storage)
|
||||
{
|
||||
DestroyCursor(cursor);
|
||||
DestroyIcon(hicon);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new (storage) GpCursor_Win32(reinterpret_cast<HCURSOR>(cursor));
|
||||
return new (storage) GpColorCursor_Win32(reinterpret_cast<HCURSOR>(hicon));
|
||||
}
|
||||
|
||||
GpCursor_Win32::GpCursor_Win32(HCURSOR cursor)
|
||||
GpColorCursor_Win32::GpColorCursor_Win32(HCURSOR cursor)
|
||||
: m_cursor(cursor)
|
||||
, m_refCount(1)
|
||||
{
|
||||
}
|
||||
|
||||
GpCursor_Win32::~GpCursor_Win32()
|
||||
GpColorCursor_Win32::~GpColorCursor_Win32()
|
||||
{
|
||||
DestroyCursor(m_cursor);
|
||||
DestroyIcon(m_cursor);
|
||||
}
|
||||
|
||||
const HCURSOR &GpCursor_Win32::GetHCursor() const
|
||||
const HCURSOR &GpColorCursor_Win32::GetHCursor() const
|
||||
{
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
void GpCursor_Win32::IncRef()
|
||||
void GpColorCursor_Win32::IncRef()
|
||||
{
|
||||
m_refCount++;
|
||||
}
|
||||
|
||||
void GpCursor_Win32::DecRef()
|
||||
void GpColorCursor_Win32::DecRef()
|
||||
{
|
||||
m_refCount--;
|
||||
if (m_refCount == 0)
|
||||
{
|
||||
this->~GpCursor_Win32();
|
||||
this->~GpColorCursor_Win32();
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "IGpColorCursor.h"
|
||||
#include "IGpCursor_Win32.h"
|
||||
#include "GpWindows.h"
|
||||
|
||||
struct IGpColorCursor_Win32 : public IGpColorCursor
|
||||
{
|
||||
virtual const HCURSOR &GetHCursor() const = 0;
|
||||
|
||||
virtual void IncRef() = 0;
|
||||
virtual void DecRef() = 0;
|
||||
};
|
||||
|
||||
|
||||
class GpColorCursor_Win32 final : public IGpColorCursor_Win32
|
||||
class GpColorCursor_Win32 final : public IGpCursor_Win32
|
||||
{
|
||||
public:
|
||||
void Destroy() override;
|
||||
@@ -22,7 +14,7 @@ public:
|
||||
void IncRef() override;
|
||||
void DecRef() override;
|
||||
|
||||
static IGpColorCursor_Win32 *Load(const wchar_t *path);
|
||||
static IGpCursor_Win32 *Create(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY);
|
||||
|
||||
private:
|
||||
GpColorCursor_Win32(HCURSOR cursor);
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "IGpCursor_Win32.h"
|
||||
#include "GpWindows.h"
|
||||
|
||||
|
||||
class GpCursor_Win32 final : public IGpCursor_Win32
|
||||
{
|
||||
public:
|
||||
void Destroy() override;
|
||||
|
||||
const HCURSOR &GetHCursor() const override;
|
||||
|
||||
void IncRef() override;
|
||||
void DecRef() override;
|
||||
|
||||
static IGpCursor_Win32 *Load(const wchar_t *path);
|
||||
|
||||
private:
|
||||
GpCursor_Win32(HCURSOR cursor);
|
||||
~GpCursor_Win32();
|
||||
|
||||
HCURSOR m_cursor;
|
||||
int m_refCount;
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "GpMain.h"
|
||||
#include "GpAudioDriverFactory.h"
|
||||
#include "GpCursor_Win32.h"
|
||||
#include "GpBWCursor_Win32.h"
|
||||
#include "GpColorCursor_Win32.h"
|
||||
#include "GpDisplayDriverFactory.h"
|
||||
#include "GpGlobalConfig.h"
|
||||
#include "GpFiber_Win32.h"
|
||||
@@ -427,7 +428,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
g_gpWindowsGlobals.m_hIconSm = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON2));
|
||||
|
||||
g_gpWindowsGlobals.m_createFiberFunc = GpFiber_Win32::Create;
|
||||
g_gpWindowsGlobals.m_loadCursorFunc = GpCursor_Win32::Load;
|
||||
g_gpWindowsGlobals.m_createBWCursorFunc = GpBWCursor_Win32::Create;
|
||||
g_gpWindowsGlobals.m_createColorCursorFunc = GpColorCursor_Win32::Create;
|
||||
g_gpWindowsGlobals.m_translateWindowsMessageFunc = TranslateWindowsMessage;
|
||||
|
||||
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11;
|
||||
|
||||
Reference in New Issue
Block a user