refactor: 使用 CursorManager 获取光标信息

This commit is contained in:
刘旭 2023-07-09 23:16:50 +08:00
commit e293bcd1b2
9 changed files with 73 additions and 37 deletions

View file

@ -13,6 +13,7 @@
#include "Win32Utils.h"
#include "ScalingWindow.h"
#include "Renderer.h"
#include "CursorManager.h"
using namespace DirectX;
@ -97,7 +98,10 @@ bool CursorDrawer::Initialize(DeviceResources& deviceResources, ID3D11Texture2D*
return true;
}
void CursorDrawer::Draw(HCURSOR hCursor, POINT cursorPos) noexcept {
void CursorDrawer::Draw() noexcept {
const CursorManager& cursorManager = ScalingWindow::Get().CursorManager();
const HCURSOR hCursor = cursorManager.Cursor();
if (!hCursor) {
return;
}
@ -107,8 +111,10 @@ void CursorDrawer::Draw(HCURSOR hCursor, POINT cursorPos) noexcept {
return;
}
const POINT cursorPos = cursorManager.CursorPos();
const float cursorScaling = ScalingWindow::Get().Options().cursorScaling;
SIZE cursorSize{ lroundf(ci->size.cx * cursorScaling), lroundf(ci->size.cy * cursorScaling) };
const SIZE cursorSize{ lroundf(ci->size.cx * cursorScaling), lroundf(ci->size.cy * cursorScaling) };
RECT cursorRect;
cursorRect.left = lroundf(cursorPos.x - ci->hotSpot.x * cursorScaling);
cursorRect.top = lroundf(cursorPos.y - ci->hotSpot.y * cursorScaling);
@ -168,6 +174,7 @@ void CursorDrawer::Draw(HCURSOR hCursor, POINT cursorPos) noexcept {
1.0f
};
d3dDC->RSSetViewports(1, &vp);
d3dDC->RSSetState(nullptr);
}
CursorInterpolationMode interpolationMode = ScalingWindow::Get().Options().cursorInterpolationMode;

View file

@ -14,7 +14,7 @@ public:
bool Initialize(DeviceResources& deviceResources, ID3D11Texture2D* backBuffer) noexcept;
void Draw(HCURSOR hCursor, POINT cursorPos) noexcept;
void Draw() noexcept;
private:
enum class _CursorType {

View file

@ -13,7 +13,7 @@ namespace Magpie::Core {
// 将源窗口的光标位置映射到缩放后的光标位置
// 当光标位于源窗口之外,与源窗口的距离不会缩放
static POINT SrcToScaling(POINT pt, bool screenCoord) noexcept {
static POINT SrcToScaling(POINT pt) noexcept {
const Renderer& renderer = ScalingWindow::Get().Renderer();
const RECT& srcRect = renderer.SrcRect();
const RECT& destRect = renderer.DestRect();
@ -39,11 +39,6 @@ static POINT SrcToScaling(POINT pt, bool screenCoord) noexcept {
result.y = std::lround(pos * (destRect.bottom - destRect.top - 1)) + destRect.top;
}
if (!screenCoord) {
result.x -= scalingRect.left;
result.y -= scalingRect.top;
}
return result;
}
@ -104,33 +99,33 @@ bool CursorManager::Initialize() noexcept {
return true;
}
std::pair<HCURSOR, POINT> CursorManager::Update() noexcept {
void CursorManager::Update() noexcept {
_UpdateCursorClip();
std::pair<HCURSOR, POINT> result{NULL,
{ std::numeric_limits<LONG>::max(), std::numeric_limits<LONG>::max() }};
_hCursor = NULL;
const ScalingOptions& options = ScalingWindow::Get().Options();
if (!options.IsDrawCursor() || !_isUnderCapture) {
// 不绘制光标
return result;
return;
}
CURSORINFO ci{ sizeof(CURSORINFO) };
if (!GetCursorInfo(&ci)) {
Logger::Get().Win32Error("GetCursorPos 失败");
return result;
return;
}
if (ci.hCursor && ci.flags != CURSOR_SHOWING) {
return result;
return;
}
result.first = ci.hCursor;
result.second = SrcToScaling(ci.ptScreenPos, false);
return result;
_hCursor = ci.hCursor;
_cursorPos = SrcToScaling(ci.ptScreenPos);
const RECT& scalingRect = ScalingWindow::Get().WndRect();
_cursorPos.x -= scalingRect.left;
_cursorPos.y -= scalingRect.top;
}
void CursorManager::_ShowSystemCursor(bool show) {
@ -326,7 +321,7 @@ void CursorManager::_UpdateCursorClip() noexcept {
//
///////////////////////////////////////////////////////////
HWND hwndCur = WindowFromPoint(hwndScaling, scalingRect, SrcToScaling(cursorPos, true), false);
HWND hwndCur = WindowFromPoint(hwndScaling, scalingRect, SrcToScaling(cursorPos), false);
if (hwndCur != hwndScaling) {
// 主窗口被遮挡
@ -460,7 +455,7 @@ void CursorManager::_UpdateCursorClip() noexcept {
// 处理屏幕之间存在间隙的情况。解决办法是 _StopCapture 只在目标位置存在屏幕时才取消捕获,
// 当光标试图移动到间隙中时将被挡住。如果光标的速度足以跨越间隙,则它依然可以在屏幕间移动。
::GetCursorPos(&cursorPos);
POINT hostPos = false ? cursorPos : SrcToScaling(cursorPos, true);
POINT hostPos = false ? cursorPos : SrcToScaling(cursorPos);
RECT clips{ LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX };
@ -556,7 +551,7 @@ void CursorManager::_StopCapture(POINT cursorPos, bool onDestroy) noexcept {
//
// 在有黑边的情况下自动将光标调整到全屏窗口外
POINT newCursorPos = SrcToScaling(cursorPos, true);
POINT newCursorPos = SrcToScaling(cursorPos);
if (onDestroy || MonitorFromPoint(newCursorPos, MONITOR_DEFAULTTONULL)) {
SetCursorPos(newCursorPos.x, newCursorPos.y);

View file

@ -12,7 +12,16 @@ public:
bool Initialize() noexcept;
std::pair<HCURSOR, POINT> Update() noexcept;
void Update() noexcept;
HCURSOR Cursor() const noexcept {
return _hCursor;
}
// 缩放窗口局部坐标
POINT CursorPos() const noexcept {
return _cursorPos;
}
private:
void _ShowSystemCursor(bool show);
@ -25,6 +34,9 @@ private:
void _StopCapture(POINT cursorPos, bool onDestroy = false) noexcept;
HCURSOR _hCursor = NULL;
POINT _cursorPos{};
RECT _curClips{};
int _originCursorSpeed = 0;

View file

@ -9,6 +9,7 @@
#include "Logger.h"
#include "Win32Utils.h"
#include "ScalingWindow.h"
#include "CursorManager.h"
namespace Magpie::Core {
@ -276,9 +277,9 @@ void ImGuiImpl::Tooltip(const char* /*content*/, float /*maxWidth*/) {
}
void ImGuiImpl::_UpdateMousePos() noexcept {
/*ImGuiIO& io = ImGui::GetIO();
ImGuiIO& io = ImGui::GetIO();
if (MagApp::Get().GetOptions().Is3DGameMode() && !MagApp::Get().GetRenderer().IsUIVisiable()) {
/*if (ScalingWindow::Get().Options().Is3DGameMode() && !MagApp::Get().GetRenderer().IsUIVisiable()) {
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
return;
}
@ -298,13 +299,22 @@ void ImGuiImpl::_UpdateMousePos() noexcept {
const RECT& hostRect = MagApp::Get().GetHostWndRect();
pos.x -= hostRect.left;
pos.y -= hostRect.top;
}*/
const CursorManager& cursorManager = ScalingWindow::Get().CursorManager();
if (!cursorManager.Cursor()) {
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
return;
}
const RECT& outputRect = MagApp::Get().GetRenderer().GetOutputRect();
pos.x -= outputRect.left;
pos.y -= outputRect.top;
const POINT cursorPos = cursorManager.CursorPos();
const RECT& scalingRect = ScalingWindow::Get().WndRect();
const RECT& destRect = ScalingWindow::Get().Renderer().DestRect();
io.MousePos = ImVec2((float)pos.x, (float)pos.y);*/
io.MousePos = ImVec2(
float(cursorPos.x + scalingRect.left - destRect.left),
float(cursorPos.y + scalingRect.top - destRect.top)
);
}
void ImGuiImpl::ClearStates() {

View file

@ -14,6 +14,7 @@
#include <dispatcherqueue.h>
#include "ScalingWindow.h"
#include "OverlayDrawer.h"
#include "CursorManager.h"
namespace Magpie::Core {
@ -236,7 +237,7 @@ void Renderer::_FrontendRender() noexcept {
}
// 绘制光标
_cursorDrawer.Draw(_lastCursorHandle, _lastCursorPos);
_cursorDrawer.Draw();
// 两个垂直同步之间允许渲染数帧SyncInterval = 0 只呈现最新的一帧,旧帧被丢弃
_swapChain->Present(0, 0);
@ -245,11 +246,20 @@ void Renderer::_FrontendRender() noexcept {
d3dDC->DiscardView(backBufferRtv);
}
void Renderer::Render(HCURSOR hCursor, POINT cursorPos) noexcept {
void Renderer::Render() noexcept {
const CursorManager& cursorManager = ScalingWindow::Get().CursorManager();
const HCURSOR hCursor = cursorManager.Cursor();
const POINT cursorPos = cursorManager.CursorPos();
// 有新帧或光标改变则渲染新的帧
if (_lastAccessMutexKey == _sharedTextureMutexKey) {
if (_lastAccessMutexKey == 0 || (hCursor == _lastCursorHandle && cursorPos == _lastCursorPos)) {
// 第一帧尚未完成或光标没有移动
if (_lastAccessMutexKey == 0) {
// 第一帧尚未完成
return;
}
if (hCursor == _lastCursorHandle && (!hCursor || cursorPos == _lastCursorPos)) {
// 光标没有移动
return;
}
}

View file

@ -17,7 +17,7 @@ public:
bool Initialize() noexcept;
void Render(HCURSOR hCursor, POINT cursorPos) noexcept;
void Render() noexcept;
void ToggleOverlay() noexcept;

View file

@ -199,8 +199,8 @@ void ScalingWindow::Render() noexcept {
return;
}
std::pair<HCURSOR, POINT> cursorInfo = _cursorManager->Update();
_renderer->Render(cursorInfo.first, cursorInfo.second);
_cursorManager->Update();
_renderer->Render();
}
void ScalingWindow::ToggleOverlay() noexcept {

View file

@ -4,6 +4,8 @@
namespace Magpie::Core {
class CursorManager;
class ScalingWindow : public WindowBase<ScalingWindow> {
friend class base_type;
@ -35,7 +37,7 @@ public:
return *_renderer;
}
class CursorManager& CursorManager() noexcept {
CursorManager& CursorManager() noexcept {
return *_cursorManager;
}