diff --git a/src/modules/MeasureTool/MeasureToolCore/BGRATextureView.h b/src/modules/MeasureTool/MeasureToolCore/BGRATextureView.h index 18ceaeab45..3f5e622581 100644 --- a/src/modules/MeasureTool/MeasureToolCore/BGRATextureView.h +++ b/src/modules/MeasureTool/MeasureToolCore/BGRATextureView.h @@ -9,6 +9,8 @@ #endif #include #include +#include + //#define DEBUG_TEXTURE @@ -125,3 +127,43 @@ struct BGRATextureView void SaveAsBitmap(const char* filename) const; #endif }; + +class MappedTextureView +{ + winrt::com_ptr context; + winrt::com_ptr texture; + +public: + BGRATextureView view; + MappedTextureView(winrt::com_ptr _texture, + winrt::com_ptr _context, + const size_t textureWidth, + const size_t textureHeight) : + texture{ std::move(_texture) }, context{ std::move(_context) } + { + D3D11_TEXTURE2D_DESC desc; + texture->GetDesc(&desc); + + D3D11_MAPPED_SUBRESOURCE resource = {}; + winrt::check_hresult(context->Map(texture.get(), D3D11CalcSubresource(0, 0, 0), D3D11_MAP_READ, 0, &resource)); + + view.pixels = static_cast(resource.pData); + view.pitch = resource.RowPitch / 4; + view.width = textureWidth; + view.height = textureHeight; + } + + MappedTextureView(MappedTextureView&&) = default; + MappedTextureView& operator=(MappedTextureView&&) = default; + + inline winrt::com_ptr GetTexture() const + { + return texture; + } + + ~MappedTextureView() + { + if (context && texture) + context->Unmap(texture.get(), D3D11CalcSubresource(0, 0, 0)); + } +}; \ No newline at end of file diff --git a/src/modules/MeasureTool/MeasureToolCore/BoundsToolOverlayUI.cpp b/src/modules/MeasureTool/MeasureToolCore/BoundsToolOverlayUI.cpp index 02b5872b73..2d0d0b394e 100644 --- a/src/modules/MeasureTool/MeasureToolCore/BoundsToolOverlayUI.cpp +++ b/src/modules/MeasureTool/MeasureToolCore/BoundsToolOverlayUI.cpp @@ -25,6 +25,8 @@ LRESULT CALLBACK BoundsToolWndProc(HWND window, UINT message, WPARAM wparam, LPA break; case WM_LBUTTONDOWN: { + for (; ShowCursor(false) >= 0;) + ; auto toolState = GetWindowParam(window); if (!toolState) break; @@ -36,6 +38,9 @@ LRESULT CALLBACK BoundsToolWndProc(HWND window, UINT message, WPARAM wparam, LPA } case WM_CURSOR_LEFT_MONITOR: { + for (; ShowCursor(true) < 0;) + ; + auto toolState = GetWindowParam(window); if (!toolState) break; @@ -44,6 +49,9 @@ LRESULT CALLBACK BoundsToolWndProc(HWND window, UINT message, WPARAM wparam, LPA } case WM_LBUTTONUP: { + for (; ShowCursor(true) < 0;) + ; + auto toolState = GetWindowParam(window); if (!toolState || !toolState->perScreen[window].currentRegionStart) break; @@ -67,6 +75,9 @@ LRESULT CALLBACK BoundsToolWndProc(HWND window, UINT message, WPARAM wparam, LPA } case WM_RBUTTONUP: { + for (; ShowCursor(true) < 0;) + ; + auto toolState = GetWindowParam(window); if (!toolState) break; diff --git a/src/modules/MeasureTool/MeasureToolCore/MeasureToolOverlayUI.cpp b/src/modules/MeasureTool/MeasureToolCore/MeasureToolOverlayUI.cpp index 216ee46cb6..a2e8d1fae7 100644 --- a/src/modules/MeasureTool/MeasureToolCore/MeasureToolOverlayUI.cpp +++ b/src/modules/MeasureTool/MeasureToolCore/MeasureToolOverlayUI.cpp @@ -13,7 +13,7 @@ namespace inline std::pair ComputeCrossFeetLine(D2D_POINT_2F center, const bool horizontal) { D2D_POINT_2F start = center, end = center; - // Computing in this way to achieve pixel-perfect axial symmetry of aliased D2D lines + // Computing in this way to achieve pixel-perfect axial symmetry of aliased D2D lines if (horizontal) { start.x -= consts::FEET_HALF_LENGTH + 1.f; @@ -36,33 +36,23 @@ namespace } winrt::com_ptr ConvertID3D11Texture2DToD2D1Bitmap(wil::com_ptr rt, - winrt::com_ptr texture) + const MappedTextureView* capturedScreenTexture) { std::lock_guard guard{ gpuAccessLock }; - auto dxgiSurface = texture.try_as(); - if (!dxgiSurface) - return nullptr; - - DXGI_MAPPED_RECT bitmap2Dmap = {}; - HRESULT hr = dxgiSurface->Map(&bitmap2Dmap, DXGI_MAP_READ); - if (FAILED(hr)) - { - return nullptr; - } + capturedScreenTexture->view.pixels; D2D1_BITMAP_PROPERTIES props = { .pixelFormat = rt->GetPixelFormat() }; rt->GetDpi(&props.dpiX, &props.dpiY); const auto sizeF = rt->GetSize(); winrt::com_ptr bitmap; - if (FAILED(rt->CreateBitmap(D2D1::SizeU(static_cast(sizeF.width), - static_cast(sizeF.height)), - bitmap2Dmap.pBits, - bitmap2Dmap.Pitch, - props, - bitmap.put()))) - return nullptr; - if (FAILED(dxgiSurface->Unmap())) + auto hr = rt->CreateBitmap(D2D1::SizeU(static_cast(capturedScreenTexture->view.width), + static_cast(capturedScreenTexture->view.height)), + capturedScreenTexture->view.pixels, + static_cast(capturedScreenTexture->view.pitch * 4), + props, + bitmap.put()); + if (FAILED(hr)) return nullptr; return bitmap; @@ -90,7 +80,7 @@ LRESULT CALLBACK MeasureToolWndProc(HWND window, UINT message, WPARAM wparam, LP StoreWindowParam(window, state); #if !defined(DEBUG_OVERLAY) - for (; ShowCursor(false) > 0;) + for (; ShowCursor(false) >= 0;) ; #endif break; @@ -142,7 +132,7 @@ void DrawMeasureToolTick(const CommonState& commonState, RECT measuredEdges{}; MeasureToolState::Mode mode = {}; winrt::com_ptr backgroundBitmap; - winrt::com_ptr backgroundTextureToConvert; + const MappedTextureView* backgroundTextureToConvert = nullptr; toolState.Read([&](const MeasureToolState& state) { continuousCapture = state.global.continuousCapture; diff --git a/src/modules/MeasureTool/MeasureToolCore/OverlayUI.cpp b/src/modules/MeasureTool/MeasureToolCore/OverlayUI.cpp index c798e91193..fbcf5bcd89 100644 --- a/src/modules/MeasureTool/MeasureToolCore/OverlayUI.cpp +++ b/src/modules/MeasureTool/MeasureToolCore/OverlayUI.cpp @@ -39,18 +39,24 @@ HWND CreateOverlayUIWindow(const CommonState& commonState, std::call_once(windowClassesCreatedFlag, CreateOverlayWindowClasses); const auto screenArea = monitor.GetScreenSize(true); - HWND window{ CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, - windowClass, - L"PowerToys.MeasureToolOverlay", - WS_POPUP, - screenArea.left(), - screenArea.top(), - screenArea.width(), - screenArea.height(), - HWND_DESKTOP, - nullptr, - GetModuleHandleW(nullptr), - extraParam) }; + DWORD windowStyle = WS_EX_TOOLWINDOW; +#if !defined(DEBUG_OVERLAY) + windowStyle |= WS_EX_TOPMOST; +#endif + HWND window{ + CreateWindowExW(windowStyle, + windowClass, + L"PowerToys.MeasureToolOverlay", + WS_POPUP, + screenArea.left(), + screenArea.top(), + screenArea.width(), + screenArea.height(), + HWND_DESKTOP, + nullptr, + GetModuleHandleW(nullptr), + extraParam) + }; winrt::check_bool(window); ShowWindow(window, SW_SHOWNORMAL); #if !defined(DEBUG_OVERLAY) diff --git a/src/modules/MeasureTool/MeasureToolCore/PerGlyphOpacityTextRender.cpp b/src/modules/MeasureTool/MeasureToolCore/PerGlyphOpacityTextRender.cpp index 7d02785951..4ccd9d9f0e 100644 --- a/src/modules/MeasureTool/MeasureToolCore/PerGlyphOpacityTextRender.cpp +++ b/src/modules/MeasureTool/MeasureToolCore/PerGlyphOpacityTextRender.cpp @@ -6,9 +6,9 @@ PerGlyphOpacityTextRender::PerGlyphOpacityTextRender( wil::com_ptr pD2DFactory, wil::com_ptr rt, wil::com_ptr baseBrush) : - _pD2DFactory{ pD2DFactory }, - _rt{ rt }, - _baseBrush{ baseBrush } + _pD2DFactory{ pD2DFactory.get() }, + _rt{ rt.get() }, + _baseBrush{ baseBrush.get() } { } @@ -18,20 +18,22 @@ HRESULT __stdcall PerGlyphOpacityTextRender::DrawGlyphRun(void* /*clientDrawingC DWRITE_MEASURING_MODE measuringMode, _In_ const DWRITE_GLYPH_RUN* glyphRun, _In_ const DWRITE_GLYPH_RUN_DESCRIPTION* /*glyphRunDescription*/, - IUnknown* clientDrawingEffect) noexcept + IUnknown* clientDrawingEffect_) noexcept { HRESULT hr = S_OK; - if (!clientDrawingEffect) + if (!clientDrawingEffect_) { - _rt->DrawGlyphRun(D2D1_POINT_2F{ .x = baselineOriginX, .y = baselineOriginY }, glyphRun, _baseBrush.get(), measuringMode); + _rt->DrawGlyphRun(D2D1_POINT_2F{ .x = baselineOriginX, .y = baselineOriginY }, glyphRun, _baseBrush, measuringMode); return hr; } + wil::com_ptr clientDrawingEffect{ clientDrawingEffect_ }; + // Create the path geometry. wil::com_ptr pathGeometry; hr = _pD2DFactory->CreatePathGeometry(&pathGeometry); // Write to the path geometry using the geometry sink. - ID2D1GeometrySink* pSink = nullptr; + wil::com_ptr pSink; if (SUCCEEDED(hr)) { hr = pathGeometry->Open(&pSink); @@ -49,11 +51,10 @@ HRESULT __stdcall PerGlyphOpacityTextRender::DrawGlyphRun(void* /*clientDrawingC glyphRun->glyphCount, glyphRun->isSideways, glyphRun->bidiLevel % 2, - pSink); + pSink.get()); } - // Close the geometry sink - if (SUCCEEDED(hr)) + if (pSink) { hr = pSink->Close(); } @@ -70,21 +71,15 @@ HRESULT __stdcall PerGlyphOpacityTextRender::DrawGlyphRun(void* /*clientDrawingC } float prevOpacity = _baseBrush->GetOpacity(); - OpacityEffect* opacityEffect = nullptr; - if (SUCCEEDED(hr)) - { - hr = clientDrawingEffect->QueryInterface(__uuidof(IDrawingEffect), reinterpret_cast(&opacityEffect)); - } + auto opacityEffect = clientDrawingEffect.try_query(); + + if (opacityEffect) + _baseBrush->SetOpacity(static_cast(opacityEffect.get())->alpha); if (SUCCEEDED(hr)) { - _baseBrush->SetOpacity(opacityEffect->alpha); - } - - if (SUCCEEDED(hr)) - { - _rt->DrawGeometry(pTransformedGeometry.get(), _baseBrush.get()); - _rt->FillGeometry(pTransformedGeometry.get(), _baseBrush.get()); + _rt->DrawGeometry(pTransformedGeometry.get(), _baseBrush); + _rt->FillGeometry(pTransformedGeometry.get(), _baseBrush); _baseBrush->SetOpacity(prevOpacity); } diff --git a/src/modules/MeasureTool/MeasureToolCore/PerGlyphOpacityTextRender.h b/src/modules/MeasureTool/MeasureToolCore/PerGlyphOpacityTextRender.h index 21cbbae661..bc36240b1e 100644 --- a/src/modules/MeasureTool/MeasureToolCore/PerGlyphOpacityTextRender.h +++ b/src/modules/MeasureTool/MeasureToolCore/PerGlyphOpacityTextRender.h @@ -16,9 +16,9 @@ struct OpacityEffect : winrt::implements struct PerGlyphOpacityTextRender : winrt::implements { - wil::com_ptr _pD2DFactory; - wil::com_ptr _rt; - wil::com_ptr _baseBrush; + ID2D1Factory * _pD2DFactory = nullptr; + ID2D1HwndRenderTarget* _rt = nullptr; + ID2D1SolidColorBrush* _baseBrush = nullptr; PerGlyphOpacityTextRender( wil::com_ptr pD2DFactory, diff --git a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp index 7dcf664df3..98fba44d0f 100644 --- a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp +++ b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp @@ -31,8 +31,8 @@ namespace winrt::PowerToys::MeasureToolCore::implementation } Core::Core() : - _mouseCaptureThread{ [this] { MouseCaptureThread(); } }, - _stopMouseCaptureThreadSignal{ wil::EventOptions::ManualReset } + _stopMouseCaptureThreadSignal{ wil::EventOptions::ManualReset }, + _mouseCaptureThread{ [this] { MouseCaptureThread(); } } { Trace::RegisterProvider(); LoggerHelpers::init_logger(L"Measure Tool", L"Core", "Measure Tool"); diff --git a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.h b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.h index 5177cc31ed..d776fc3529 100644 --- a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.h +++ b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.h @@ -21,9 +21,9 @@ namespace winrt::PowerToys::MeasureToolCore::implementation float GetDPIScaleForWindow(uint64_t windowHandle); void MouseCaptureThread(); + wil::shared_event _stopMouseCaptureThreadSignal; std::thread _mouseCaptureThread; std::vector _screenCaptureThreads; - wil::shared_event _stopMouseCaptureThreadSignal; std::vector> _overlayUIStates; Serialized _measureToolState; diff --git a/src/modules/MeasureTool/MeasureToolCore/ScreenCapturing.cpp b/src/modules/MeasureTool/MeasureToolCore/ScreenCapturing.cpp index 00b60a3897..b55d77008b 100644 --- a/src/modules/MeasureTool/MeasureToolCore/ScreenCapturing.cpp +++ b/src/modules/MeasureTool/MeasureToolCore/ScreenCapturing.cpp @@ -10,46 +10,6 @@ //#define DEBUG_EDGES -class MappedTextureView -{ - winrt::com_ptr context; - winrt::com_ptr texture; - -public: - BGRATextureView view; - MappedTextureView(winrt::com_ptr _texture, - winrt::com_ptr _context, - const size_t textureWidth, - const size_t textureHeight) : - texture{ std::move(_texture) }, context{ std::move(_context) } - { - D3D11_TEXTURE2D_DESC desc; - texture->GetDesc(&desc); - - D3D11_MAPPED_SUBRESOURCE resource = {}; - winrt::check_hresult(context->Map(texture.get(), D3D11CalcSubresource(0, 0, 0), D3D11_MAP_READ, 0, &resource)); - - view.pixels = static_cast(resource.pData); - view.pitch = resource.RowPitch / 4; - view.width = textureWidth; - view.height = textureHeight; - } - - MappedTextureView(MappedTextureView&&) = default; - MappedTextureView& operator=(MappedTextureView&&) = default; - - inline winrt::com_ptr GetTexture() const - { - return texture; - } - - ~MappedTextureView() - { - if (context && texture) - context->Unmap(texture.get(), D3D11CalcSubresource(0, 0, 0)); - } -}; - class D3DCaptureState final { winrt::com_ptr d3dDevice; @@ -171,8 +131,10 @@ void D3DCaptureState::OnFrameArrived(const winrt::Direct3D11CaptureFramePool& se } winrt::check_hresult(swapChain->GetBuffer(0, winrt::guid_of(), texture.put_void())); - auto gpuTexture = GetDXGIInterfaceFromObject(frame.Surface()); + auto surface = frame.Surface(); + auto gpuTexture = GetDXGIInterfaceFromObject(surface); texture = CopyFrameToCPU(gpuTexture); + surface.Close(); MappedTextureView textureView{ texture, context, static_cast(frameSize.Width), static_cast(frameSize.Height) }; frameCallback(std::move(textureView)); @@ -227,6 +189,7 @@ std::unique_ptr D3DCaptureState::Create(winrt::GraphicsCaptureI nullptr); } winrt::check_hresult(hr); + auto dxgiDevice = d3dDevice.as(); winrt::com_ptr d3dDeviceInspectable; @@ -413,7 +376,7 @@ std::thread StartCapturingThread(const CommonState& commonState, const auto textureView = captureState->CaptureSingleFrame(); state.Access([&](MeasureToolState& s) { - s.perScreen[window].capturedScreenTexture = textureView.GetTexture(); + s.perScreen[window].capturedScreenTexture = &textureView; }); while (IsWindow(window) && !commonState.closeOnOtherMonitors) diff --git a/src/modules/MeasureTool/MeasureToolCore/ToolState.h b/src/modules/MeasureTool/MeasureToolCore/ToolState.h index b97064fb57..e5222892f0 100644 --- a/src/modules/MeasureTool/MeasureToolCore/ToolState.h +++ b/src/modules/MeasureTool/MeasureToolCore/ToolState.h @@ -15,6 +15,7 @@ #include //#define DEBUG_OVERLAY +#include "BGRATextureView.h" struct OverlayBoxText { @@ -69,7 +70,7 @@ struct MeasureToolState RECT measuredEdges = {}; // While not in a continuous capturing mode, we need to draw captured backgrounds. These are passed // directly from a capturing thread. - winrt::com_ptr capturedScreenTexture; + const MappedTextureView* capturedScreenTexture = nullptr; // After the drawing thread finds its capturedScreenTexture, it converts it to // a Direct2D compatible bitmap and caches it here winrt::com_ptr capturedScreenBitmap;