From a95db00606dd07f954dfe54d175e183e21bb00ed Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 27 Mar 2023 11:34:21 -0400 Subject: [PATCH 1/2] Limit cursor clipping to the render area --- src/d2dx/RenderContext.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/d2dx/RenderContext.cpp b/src/d2dx/RenderContext.cpp index 9beb040..67f95c8 100644 --- a/src/d2dx/RenderContext.cpp +++ b/src/d2dx/RenderContext.cpp @@ -400,7 +400,7 @@ void RenderContext::Present() UpdateViewport(_renderRect); RenderContextPixelShader pixelShader; - + switch (_d2dxContext->GetOptions().GetFiltering()) { default: @@ -1026,11 +1026,15 @@ void RenderContext::ClipCursor() return; } - RECT clipRect; - ::GetClientRect(_hWnd, &clipRect); + RECT clipRect = { + _renderRect.offset.x, + _renderRect.offset.y, + _renderRect.offset.x + _renderRect.size.width, + _renderRect.offset.y + _renderRect.size.height + }; ::ClientToScreen(_hWnd, (LPPOINT)&clipRect.left); - ::ClientToScreen(_hWnd, (LPPOINT)&clipRect.right); - ::ClipCursor(&clipRect); + ::ClientToScreen(_hWnd, (LPPOINT)&clipRect.right); + ::ClipCursor(&clipRect); } void RenderContext::UnclipCursor() From 6824ce31ab01f27b0370b3cbb16f7284287b3229 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 27 Mar 2023 11:34:21 -0400 Subject: [PATCH 2/2] Only lock the cursor when the mouse interacts with the client area --- src/d2dx/RenderContext.cpp | 23 +++++++++++++++++------ src/d2dx/RenderContext.h | 12 +++++++++++- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/d2dx/RenderContext.cpp b/src/d2dx/RenderContext.cpp index 67f95c8..f3dd92b 100644 --- a/src/d2dx/RenderContext.cpp +++ b/src/d2dx/RenderContext.cpp @@ -85,6 +85,7 @@ RenderContext::RenderContext( GetClientRect(hWnd, &clientRect); SetWindowSubclass((HWND)hWnd, d2dxSubclassWndProc, 1234, (DWORD_PTR)this); + _isActiveWindow = GetForegroundWindow() == hWnd; const int32_t widthFromClientRect = clientRect.right - clientRect.left; const int32_t heightFromClientRect = clientRect.bottom - clientRect.top; @@ -685,17 +686,20 @@ static LRESULT CALLBACK d2dxSubclassWndProc( { RenderContext* renderContext = (RenderContext*)dwRefData; - if (uMsg == WM_ACTIVATEAPP) + if (uMsg == WM_ACTIVATE) { if (wParam) { - renderContext->ClipCursor(); + renderContext->SetActiveWindow(true); } else { - renderContext->UnclipCursor(); + renderContext->SetActiveWindow(false); } } + else if (uMsg == WM_MOVING) { + renderContext->UnclipCursor(); + } else if (uMsg == WM_SYSKEYDOWN || uMsg == WM_KEYDOWN) { if (wParam == VK_RETURN && (HIWORD(lParam) & KF_ALTDOWN)) @@ -719,6 +723,11 @@ static LRESULT CALLBACK d2dxSubclassWndProc( #ifdef NDEBUG ShowCursor_Real(FALSE); #endif + if (uMsg != WM_MOUSEMOVE) + { + renderContext->ClipCursor(false); + } + Offset mousePos = { LOWORD(lParam), HIWORD(lParam) }; Size gameSize; @@ -921,7 +930,7 @@ void RenderContext::SetSizes( SetWindowPos_Real(_hWnd, HWND_TOP, 0, 0, _desktopSize.width, _desktopSize.height, SWP_SHOWWINDOW | SWP_NOSENDCHANGING | SWP_FRAMECHANGED); } - ClipCursor(); + ClipCursor(true); if (!_d2dxContext->GetOptions().GetFlag(OptionsFlag::NoTitleChange)) { @@ -1019,9 +1028,9 @@ void RenderContext::GetCurrentMetrics( } } -void RenderContext::ClipCursor() +void RenderContext::ClipCursor(bool resizing) { - if (_d2dxContext->GetOptions().GetFlag(OptionsFlag::NoClipCursor)) + if (!_isActiveWindow || (resizing != _isCursorClipped) || _d2dxContext->GetOptions().GetFlag(OptionsFlag::NoClipCursor)) { return; } @@ -1035,11 +1044,13 @@ void RenderContext::ClipCursor() ::ClientToScreen(_hWnd, (LPPOINT)&clipRect.left); ::ClientToScreen(_hWnd, (LPPOINT)&clipRect.right); ::ClipCursor(&clipRect); + _isCursorClipped = true; } void RenderContext::UnclipCursor() { ::ClipCursor(NULL); + _isCursorClipped = false; } float RenderContext::GetFrameTime() const diff --git a/src/d2dx/RenderContext.h b/src/d2dx/RenderContext.h index cc1b919..27c158c 100644 --- a/src/d2dx/RenderContext.h +++ b/src/d2dx/RenderContext.h @@ -113,7 +113,15 @@ namespace d2dx virtual ScreenMode GetScreenMode() const override; - void ClipCursor(); + void SetActiveWindow(bool active) { + if (!active) + { + UnclipCursor(); + } + _isActiveWindow = active; + } + + void ClipCursor(bool resizing); void UnclipCursor(); private: @@ -210,6 +218,8 @@ namespace d2dx EventHandle _frameLatencyWaitableObject; int64_t _timeStart; bool _hasAdjustedWindowPlacement = false; + bool _isActiveWindow = false; + bool _isCursorClipped = false; double _prevTime; double _frameTimeMs;