1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Second attempt to fix DPI unaware cursor position

See issue #319.
This commit is contained in:
narzoul 2024-06-09 16:35:09 +02:00
parent 471cd11389
commit 3d1197f863
3 changed files with 72 additions and 28 deletions

View File

@ -37,16 +37,21 @@ namespace
return LOG_RESULT(TRUE);
}
BOOL WINAPI getClipCursor(LPRECT lpRect)
BOOL WINAPI getClipCursorInternal(LPRECT lpRect)
{
LOG_FUNC("GetClipCursor", lpRect);
Compat::ScopedCriticalSection lock(g_cs);
BOOL result = CALL_ORIG_FUNC(GetClipCursor)(lpRect);
if (result && !IsRectEmpty(&g_monitorClipRect))
{
*lpRect = g_clipRect;
}
return LOG_RESULT(result);
return result;
}
BOOL WINAPI getClipCursor(LPRECT lpRect)
{
LOG_FUNC("GetClipCursor", lpRect);
return LOG_RESULT(getClipCursorInternal(lpRect));
}
HCURSOR WINAPI getCursor()
@ -125,31 +130,18 @@ namespace Gdi
{
namespace Cursor
{
void clip()
{
Compat::ScopedCriticalSection lock(g_cs);
if (!IsRectEmpty(&g_monitorClipRect))
{
POINT cp = {};
CALL_ORIG_FUNC(GetCursorPos)(&cp);
if (!PtInRect(&g_monitorClipRect, cp))
{
clip(cp);
CALL_ORIG_FUNC(SetCursorPos)(cp.x, cp.y);
}
}
}
void clip(POINT& pt)
{
Compat::ScopedCriticalSection lock(g_cs);
if (!IsRectEmpty(&g_monitorClipRect))
RECT r = {};
if (!getClipCursorInternal(&r))
{
pt.x = std::max(pt.x, g_monitorClipRect.left);
pt.x = std::min(pt.x, g_monitorClipRect.right);
pt.y = std::max(pt.y, g_monitorClipRect.top);
pt.y = std::min(pt.y, g_monitorClipRect.bottom);
return;
}
pt.x = std::max(pt.x, r.left);
pt.x = std::min(pt.x, r.right);
pt.y = std::max(pt.y, r.top);
pt.y = std::min(pt.y, r.bottom);
}
CURSORINFO getEmulatedCursorInfo()

View File

@ -6,7 +6,6 @@ namespace Gdi
{
namespace Cursor
{
void clip();
void clip(POINT& pt);
CURSORINFO getEmulatedCursorInfo();
void installHooks();

View File

@ -92,6 +92,51 @@ namespace
return LOG_RESULT(CALL_ORIG_FUNC(AnimateWindow)(hWnd, dwTime, dwFlags));
}
void clipMouseCoords(MSG& msg)
{
Gdi::Cursor::clip(msg.pt);
bool isClient = false;
if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST)
{
isClient = WM_MOUSEWHEEL != msg.message && WM_MOUSEHWHEEL != msg.message;
}
else if (msg.message >= WM_NCMOUSEMOVE && msg.message <= WM_NCMBUTTONDBLCLK ||
msg.message >= WM_NCXBUTTONDOWN && msg.message <= WM_NCXBUTTONDBLCLK ||
WM_NCHITTEST == msg.message)
{
isClient = false;
}
else if (WM_MOUSEHOVER == msg.message ||
WM_NCMOUSEHOVER == msg.message)
{
isClient = true;
}
else
{
return;
}
POINT pt = {};
pt.x = GET_X_LPARAM(msg.lParam);
pt.y = GET_Y_LPARAM(msg.lParam);
if (isClient)
{
ClientToScreen(msg.hwnd, &pt);
}
Gdi::Cursor::clip(pt);
if (isClient)
{
ScreenToClient(msg.hwnd, &pt);
}
reinterpret_cast<POINTS*>(&msg.lParam)->x = static_cast<SHORT>(pt.x);
reinterpret_cast<POINTS*>(&msg.lParam)->y = static_cast<SHORT>(pt.y);
}
template <auto func, typename Result, typename... Params>
Result WINAPI createDialog(Params... params)
{
@ -351,8 +396,12 @@ namespace
decltype(&GetMessageA) origGetMessage)
{
DDraw::RealPrimarySurface::setUpdateReady();
Gdi::Cursor::clip();
return origGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
BOOL result = origGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
if (-1 != result)
{
clipMouseCoords(*lpMsg);
}
return result;
}
BOOL WINAPI getMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
@ -572,8 +621,12 @@ namespace
decltype(&PeekMessageA) origPeekMessage)
{
DDraw::RealPrimarySurface::setUpdateReady();
Gdi::Cursor::clip();
BOOL result = origPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (result)
{
clipMouseCoords(*lpMsg);
}
if (!g_isFrameStarted || Config::Settings::FpsLimiter::MSGLOOP != Config::fpsLimiter.get())
{
return result;