diff --git a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj index 5f300465d2..c66bd2e698 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj +++ b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj @@ -131,6 +131,7 @@ Create + @@ -144,6 +145,7 @@ + diff --git a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj.filters b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj.filters index 23f17a6993..4a12888f4a 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj.filters +++ b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj.filters @@ -45,6 +45,9 @@ Source Files + + Source Files + @@ -92,6 +95,9 @@ Resource Files + + Header Files + diff --git a/src/modules/alwaysontop/AlwaysOnTop/FrameDrawer.cpp b/src/modules/alwaysontop/AlwaysOnTop/FrameDrawer.cpp index 7293561626..9613769f2f 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/FrameDrawer.cpp +++ b/src/modules/alwaysontop/AlwaysOnTop/FrameDrawer.cpp @@ -3,6 +3,8 @@ #include +#include + namespace { size_t D2DRectUHash(D2D1_SIZE_U rect) @@ -88,7 +90,7 @@ void FrameDrawer::Show() Render(); } -void FrameDrawer::SetBorderRect(RECT windowRect, COLORREF color, int thickness, int radius) +void FrameDrawer::SetBorderRect(RECT windowRect, COLORREF color, int thickness, float radius) { auto newSceneRect = DrawableRect{ .borderColor = ConvertColor(color), @@ -181,15 +183,27 @@ D2D1_COLOR_F FrameDrawer::ConvertColor(COLORREF color) 1.f); } -D2D1_ROUNDED_RECT FrameDrawer::ConvertRect(RECT rect, int thickness, int radius) +D2D1_ROUNDED_RECT FrameDrawer::ConvertRect(RECT rect, int thickness, float radius) { - auto d2d1Rect = D2D1::RectF((float)rect.left + thickness, (float)rect.top + thickness, (float)rect.right - thickness, (float)rect.bottom - thickness); - return D2D1::RoundedRect(d2d1Rect, (float)radius, (float)radius); + float halfThickness = thickness / 2.0f; + + // 1 is needed to eliminate the gap between border and window + auto d2d1Rect = D2D1::RectF((float)rect.left + halfThickness + 1, + (float)rect.top + halfThickness + 1, + (float)rect.right - halfThickness - 1, + (float)rect.bottom - halfThickness - 1); + return D2D1::RoundedRect(d2d1Rect, radius, radius); } D2D1_RECT_F FrameDrawer::ConvertRect(RECT rect, int thickness) { - return D2D1::RectF((float)rect.left + thickness, (float)rect.top + thickness, (float)rect.right - thickness, (float)rect.bottom - thickness); + float halfThickness = thickness / 2.0f; + + // 1 is needed to eliminate the gap between border and window + return D2D1::RectF((float)rect.left + halfThickness + 1, + (float)rect.top + halfThickness + 1, + (float)rect.right - halfThickness - 1, + (float)rect.bottom - halfThickness - 1); } void FrameDrawer::Render() @@ -207,11 +221,11 @@ void FrameDrawer::Render() if (m_sceneRect.roundedRect) { - m_renderTarget->DrawRoundedRectangle(m_sceneRect.roundedRect.value(), m_borderBrush.get(), static_cast(m_sceneRect.thickness * 2)); + m_renderTarget->DrawRoundedRectangle(m_sceneRect.roundedRect.value(), m_borderBrush.get(), static_cast(m_sceneRect.thickness)); } else if (m_sceneRect.rect) { - m_renderTarget->DrawRectangle(m_sceneRect.rect.value(), m_borderBrush.get(), static_cast(m_sceneRect.thickness * 2)); + m_renderTarget->DrawRectangle(m_sceneRect.rect.value(), m_borderBrush.get(), static_cast(m_sceneRect.thickness)); } m_renderTarget->EndDraw(); diff --git a/src/modules/alwaysontop/AlwaysOnTop/FrameDrawer.h b/src/modules/alwaysontop/AlwaysOnTop/FrameDrawer.h index d3fb27d411..5d622b09f5 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/FrameDrawer.h +++ b/src/modules/alwaysontop/AlwaysOnTop/FrameDrawer.h @@ -18,7 +18,7 @@ public: void Show(); void Hide(); - void SetBorderRect(RECT windowRect, COLORREF color, int thickness, int radius); + void SetBorderRect(RECT windowRect, COLORREF color, int thickness, float radius); private: bool CreateRenderTargets(const RECT& clientRect); @@ -34,7 +34,7 @@ private: static ID2D1Factory* GetD2DFactory(); static IDWriteFactory* GetWriteFactory(); static D2D1_COLOR_F ConvertColor(COLORREF color); - static D2D1_ROUNDED_RECT ConvertRect(RECT rect, int thickness, int radius); + static D2D1_ROUNDED_RECT ConvertRect(RECT rect, int thickness, float radius); static D2D1_RECT_F ConvertRect(RECT rect, int thickness); void Render(); diff --git a/src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.cpp b/src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.cpp new file mode 100644 index 0000000000..d18f064f63 --- /dev/null +++ b/src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.cpp @@ -0,0 +1,19 @@ +#include "pch.h" +#include "ScalingUtils.h" + +#include +#include + +float ScalingUtils::ScalingFactor(HWND window) noexcept +{ + UINT dpi = 96; + auto res = DPIAware::GetScreenDPIForWindow(window, dpi); + + if (res != S_OK) + { + Logger::error(L"Failed to get DPI: {}", get_last_error_or_default(res)); + return 1.0f; + } + + return dpi / 96.0f; +} diff --git a/src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.h b/src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.h new file mode 100644 index 0000000000..1ce76e55ed --- /dev/null +++ b/src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.h @@ -0,0 +1,6 @@ +#pragma once + +namespace ScalingUtils +{ + float ScalingFactor(HWND window) noexcept; +}; diff --git a/src/modules/alwaysontop/AlwaysOnTop/WindowBorder.cpp b/src/modules/alwaysontop/AlwaysOnTop/WindowBorder.cpp index e5d4bb49de..a10ac60897 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/WindowBorder.cpp +++ b/src/modules/alwaysontop/AlwaysOnTop/WindowBorder.cpp @@ -5,6 +5,7 @@ #include "winrt/Windows.Foundation.h" #include +#include #include #include @@ -192,13 +193,15 @@ void WindowBorder::UpdateBorderProperties() const color = AlwaysOnTopSettings::settings().frameColor; } - int cornerRadius = 0; + float scalingFactor = ScalingUtils::ScalingFactor(m_trackingWindow); + float thickness = AlwaysOnTopSettings::settings().frameThickness * scalingFactor; + float cornerRadius = 0.0; if (AlwaysOnTopSettings::settings().roundCornersEnabled) { - cornerRadius = WindowBordersUtils::AreCornersRounded(m_trackingWindow) ? 8 : 0; + cornerRadius = WindowCornerUtils::CornersRadius(m_trackingWindow) * scalingFactor; } - m_frameDrawer->SetBorderRect(frameRect, color, AlwaysOnTopSettings::settings().frameThickness, cornerRadius); + m_frameDrawer->SetBorderRect(frameRect, color, static_cast(thickness), cornerRadius); } LRESULT WindowBorder::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept diff --git a/src/modules/alwaysontop/AlwaysOnTop/WindowCornersUtil.cpp b/src/modules/alwaysontop/AlwaysOnTop/WindowCornersUtil.cpp index 9a594d211f..e64ed0fd75 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/WindowCornersUtil.cpp +++ b/src/modules/alwaysontop/AlwaysOnTop/WindowCornersUtil.cpp @@ -20,9 +20,9 @@ enum DWM_WINDOW_CORNER_PREFERENCE DWMWCP_ROUNDSMALL = 3 }; -bool WindowBordersUtils::AreCornersRounded(HWND window) noexcept +int WindowCornerUtils::CornerPreference(HWND window) noexcept { - int cornerPreference = DWMWCP_DEFAULT; + int cornerPreference = -1; auto res = DwmGetWindowAttribute(window, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPreference, sizeof(cornerPreference)); if (res != S_OK) { @@ -31,9 +31,24 @@ bool WindowBordersUtils::AreCornersRounded(HWND window) noexcept { Logger::error(L"Get corner preference error: {}", get_last_error_or_default(res)); } - - return false; } - return cornerPreference != DWM_WINDOW_CORNER_PREFERENCE::DWMWCP_DONOTROUND; + return cornerPreference; +} + +int WindowCornerUtils::CornersRadius(HWND window) noexcept +{ + int cornerPreference = CornerPreference(window); + + switch (cornerPreference) + { + case DWM_WINDOW_CORNER_PREFERENCE::DWMWCP_ROUND: + return 8; + case DWM_WINDOW_CORNER_PREFERENCE::DWMWCP_ROUNDSMALL: + return 4; + case DWM_WINDOW_CORNER_PREFERENCE::DWMWCP_DEFAULT: + return 8; + default: + return 0; + } } diff --git a/src/modules/alwaysontop/AlwaysOnTop/WindowCornersUtil.h b/src/modules/alwaysontop/AlwaysOnTop/WindowCornersUtil.h index db48178532..6ac0c4ecc2 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/WindowCornersUtil.h +++ b/src/modules/alwaysontop/AlwaysOnTop/WindowCornersUtil.h @@ -1,4 +1,5 @@ -namespace WindowBordersUtils +namespace WindowCornerUtils { - bool AreCornersRounded(HWND window) noexcept; + int CornerPreference(HWND window) noexcept; + int CornersRadius(HWND window) noexcept; } \ No newline at end of file