cleanup cursor convertion between coordinate spaces

This commit is contained in:
yuyoyuppe
2022-08-26 21:48:06 +02:00
parent 4daf5714dc
commit 5df9f04dbd
10 changed files with 51 additions and 38 deletions

View File

@@ -68,7 +68,7 @@ template<typename T>
inline void StoreWindowParam(HWND window, T data)
{
static_assert(sizeof(T) <= sizeof(void*));
SetWindowLongPtrW(window, GWLP_USERDATA, (LONG_PTR)(data));
SetWindowLongPtrW(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(data));
}
template<typename T>

View File

@@ -1,5 +1,6 @@
#include "pch.h"
#include "BoundsToolOverlayUI.h"
#include "CoordinateSystemConversion.h"
#include "Clipboard.h"
#include <common/utils/window.h>
@@ -27,8 +28,7 @@ LRESULT CALLBACK BoundsToolWndProc(HWND window, UINT message, WPARAM wparam, LPA
auto toolState = GetWindowParam<BoundsToolState*>(window);
if (!toolState)
break;
POINT cursorPos = toolState->commonState->cursorPos;
ScreenToClient(window, &cursorPos);
const POINT cursorPos = convert::FromSystemToRelativeForDirect2D(window, toolState->commonState->cursorPosSystemSpace);
D2D_POINT_2F newRegionStart = { .x = static_cast<float>(cursorPos.x), .y = static_cast<float>(cursorPos.y) };
toolState->perScreen[window].currentRegionStart = newRegionStart;
@@ -54,8 +54,7 @@ LRESULT CALLBACK BoundsToolWndProc(HWND window, UINT message, WPARAM wparam, LPA
if (const bool shiftPress = GetKeyState(VK_SHIFT) & 0x8000; shiftPress)
{
auto cursorPos = toolState->commonState->cursorPos;
ScreenToClient(window, &cursorPos);
const auto cursorPos = convert::FromSystemToRelativeForDirect2D(window, toolState->commonState->cursorPosSystemSpace);
D2D1_RECT_F rect;
std::tie(rect.left, rect.right) = std::minmax(static_cast<float>(cursorPos.x), toolState->perScreen[window].currentRegionStart->x);
@@ -142,7 +141,7 @@ void DrawBoundsToolTick(const CommonState& commonState,
const auto it = toolState.perScreen.find(window);
if (it == end(toolState.perScreen))
return;
d2dState.rt->Clear();
const auto& perScreen = it->second;
@@ -152,8 +151,7 @@ void DrawBoundsToolTick(const CommonState& commonState,
if (!perScreen.currentRegionStart.has_value())
return;
POINT cursorPos = commonState.cursorPos;
ScreenToClient(window, &cursorPos);
const auto cursorPos = convert::FromSystemToRelativeForDirect2D(window, commonState.cursorPosSystemSpace);
const D2D1_RECT_F rect{ .left = perScreen.currentRegionStart->x,
.top = perScreen.currentRegionStart->y,

View File

@@ -0,0 +1,26 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
namespace convert
{
// Converts a given point from multimonitor coordinate system to the one relative to HWND
inline POINT FromSystemToRelative(HWND window, POINT p)
{
ScreenToClient(window, &p);
return p;
}
// Converts a given point from multimonitor coordinate system to the one relative to HWND and also ready
// to be used in Direct2D calls with AA mode set to aliased
inline POINT FromSystemToRelativeForDirect2D(HWND window, POINT p)
{
ScreenToClient(window, &p);
// Submitting DrawLine calls to Direct2D with thickness == 1.f and AA mode set to aliased causes
// them to be drawn offset by [1,1] toward upper-left corner, so we must to compensate for that.
++p.x;
++p.y;
return p;
}
}

View File

@@ -1,8 +1,9 @@
#include "pch.h"
#include "BGRATextureView.h"
#include "constants.h"
#include "Clipboard.h"
#include "CoordinateSystemConversion.h"
#include "constants.h"
#include "MeasureToolOverlayUI.h"
#include <common/utils/window.h>
@@ -216,8 +217,7 @@ void DrawMeasureToolTick(const CommonState& commonState,
// Anti-aliasing is creating artifacts. Aliasing is for drawing straight lines.
d2dState.rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
POINT cursorPos = commonState.cursorPos;
ScreenToClient(window, &cursorPos);
const auto cursorPos = convert::FromSystemToRelativeForDirect2D(window, commonState.cursorPosSystemSpace);
if (drawHorizontalCrossLine)
{

View File

@@ -38,7 +38,7 @@ HWND CreateOverlayUIWindow(const CommonState& commonState,
static std::once_flag windowClassesCreatedFlag;
std::call_once(windowClassesCreatedFlag, CreateOverlayWindowClasses);
const auto screenArea = monitor.GetScreenSize(false);
const auto screenArea = monitor.GetScreenSize(true);
HWND window{ CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
windowClass,
L"PowerToys.MeasureToolOverlay",
@@ -106,7 +106,7 @@ void OverlayUIState::RunUILoop()
{
_d2dState.rt->BeginDraw();
const auto cursor = _commonState.cursorPos;
const auto cursor = _commonState.cursorPosSystemSpace;
const bool cursorOverToolbar = _commonState.toolbarBoundingBox.inside(cursor);
if (!cursorOverToolbar)
_tickFunc();

View File

@@ -20,10 +20,10 @@ namespace winrt::PowerToys::MeasureToolCore::implementation
{
while (!_stopMouseCaptureThreadSignal.is_signaled())
{
static_assert(sizeof(_commonState.cursorPos) == sizeof(LONG64));
static_assert(sizeof(_commonState.cursorPosSystemSpace) == sizeof(LONG64));
POINT cursorPos = {};
GetCursorPos(&cursorPos);
InterlockedExchange64(reinterpret_cast<LONG64*>(&_commonState.cursorPos), std::bit_cast<LONG64>(cursorPos));
InterlockedExchange64(reinterpret_cast<LONG64*>(&_commonState.cursorPosSystemSpace), std::bit_cast<LONG64>(cursorPos));
std::this_thread::sleep_for(consts::TARGET_FRAME_DURATION);
}
}

View File

@@ -1,9 +1,10 @@
#include "pch.h"
#include "constants.h"
#include "ScreenCapturing.h"
#include "BGRATextureView.h"
#include "constants.h"
#include "CoordinateSystemConversion.h"
#include "EdgeDetection.h"
#include "ScreenCapturing.h"
#include <common/Display/monitors.h>
@@ -324,8 +325,7 @@ void UpdateCaptureState(const CommonState& commonState,
const MappedTextureView& textureView,
const bool continuousCapture)
{
auto cursorPos = commonState.cursorPos;
ScreenToClient(window, &cursorPos);
const auto cursorPos = convert::FromSystemToRelative(window, commonState.cursorPosSystemSpace);
const bool cursorInLeftScreenHalf = cursorPos.x < textureView.view.width / 2;
const bool cursorInTopScreenHalf = cursorPos.y < textureView.view.height / 2;
uint8_t pixelTolerance = {};
@@ -337,13 +337,6 @@ void UpdateCaptureState(const CommonState& commonState,
perColorChannelEdgeDetection = state.global.perColorChannelEdgeDetection;
});
// We must offset mouse cursor, since its position is off by one from its center (TODO: reason?)
if (cursorPos.x > 0)
--cursorPos.x;
if (cursorPos.y > 0)
--cursorPos.y;
// Every one of 4 edges is a coordinate of the last similar pixel in a row
// Example: given a 5x5 green square on a blue background with its top-left pixel
// at 20x100, bounds should be [20,100]-[24,104]. We don't include [25,105] or
@@ -424,10 +417,14 @@ std::thread StartCapturingThread(const CommonState& commonState,
while (IsWindow(window) && !commonState.closeOnOtherMonitors)
{
const auto now = std::chrono::high_resolution_clock::now();
if (monitorArea.inside(commonState.cursorPos))
if (monitorArea.inside(commonState.cursorPosSystemSpace))
{
#if defined(DEBUG_TEXTURE)
auto path = std::filesystem::temp_directory_path() / "frame.bmp";
SYSTEMTIME lt{};
GetLocalTime(&lt);
char buf[256];
sprintf_s(buf, "frame-%02d-%02d-Monitor-%zu.bmp", lt.wHour, lt.wMinute, (uint64_t)window);
auto path = std::filesystem::temp_directory_path() / buf;
textureView.view.SaveAsBitmap(path.string().c_str());
#endif
UpdateCaptureState(commonState, state, window, textureView, continuousCapture);

View File

@@ -28,7 +28,7 @@ struct CommonState
Box toolbarBoundingBox;
mutable Serialized<OverlayBoxText> overlayBoxText;
POINT cursorPos = {}; // updated atomically
POINT cursorPosSystemSpace = {}; // updated atomically
std::atomic_bool closeOnOtherMonitors = false;
};

View File

@@ -81,6 +81,7 @@ template<typename Func>
return std::thread{ [f = std::move(f), description = std::wstring{ description }] {
try
{
SetThreadDescription(GetCurrentThread(), description.c_str());
f();
}
catch (const std::exception& ex)

View File

@@ -1,20 +1,11 @@
#pragma once
#define COMPOSITION
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <strsafe.h>
#include <hIdUsage.h>
#include <shellapi.h>
#ifdef COMPOSITION
#include <windows.ui.composition.interop.h>
#include <DispatcherQueue.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.UI.Composition.Desktop.h>
#endif
#include <thread>
#include <winrt/Windows.Foundation.Collections.h>