mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 03:37:59 +01:00
[AlwaysOnTop] Corners scaling (#20352)
This commit is contained in:
@@ -131,6 +131,7 @@
|
|||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="ScalingUtils.cpp" />
|
||||||
<ClCompile Include="Settings.cpp" />
|
<ClCompile Include="Settings.cpp" />
|
||||||
<ClCompile Include="trace.cpp" />
|
<ClCompile Include="trace.cpp" />
|
||||||
<ClCompile Include="VirtualDesktopUtils.cpp" />
|
<ClCompile Include="VirtualDesktopUtils.cpp" />
|
||||||
@@ -144,6 +145,7 @@
|
|||||||
<ClInclude Include="ModuleConstants.h" />
|
<ClInclude Include="ModuleConstants.h" />
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
|
<ClInclude Include="ScalingUtils.h" />
|
||||||
<ClInclude Include="Settings.h" />
|
<ClInclude Include="Settings.h" />
|
||||||
<ClInclude Include="SettingsConstants.h" />
|
<ClInclude Include="SettingsConstants.h" />
|
||||||
<ClInclude Include="SettingsObserver.h" />
|
<ClInclude Include="SettingsObserver.h" />
|
||||||
|
|||||||
@@ -45,6 +45,9 @@
|
|||||||
<ClCompile Include="WindowCornersUtil.cpp">
|
<ClCompile Include="WindowCornersUtil.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="ScalingUtils.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
@@ -92,6 +95,9 @@
|
|||||||
<ClInclude Include="resource.h">
|
<ClInclude Include="resource.h">
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="ScalingUtils.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="AlwaysOnTop.rc">
|
<ResourceCompile Include="AlwaysOnTop.rc">
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
|
|
||||||
|
#include <ScalingUtils.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
size_t D2DRectUHash(D2D1_SIZE_U rect)
|
size_t D2DRectUHash(D2D1_SIZE_U rect)
|
||||||
@@ -88,7 +90,7 @@ void FrameDrawer::Show()
|
|||||||
Render();
|
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{
|
auto newSceneRect = DrawableRect{
|
||||||
.borderColor = ConvertColor(color),
|
.borderColor = ConvertColor(color),
|
||||||
@@ -181,15 +183,27 @@ D2D1_COLOR_F FrameDrawer::ConvertColor(COLORREF color)
|
|||||||
1.f);
|
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);
|
float halfThickness = thickness / 2.0f;
|
||||||
return D2D1::RoundedRect(d2d1Rect, (float)radius, (float)radius);
|
|
||||||
|
// 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)
|
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()
|
void FrameDrawer::Render()
|
||||||
@@ -207,11 +221,11 @@ void FrameDrawer::Render()
|
|||||||
|
|
||||||
if (m_sceneRect.roundedRect)
|
if (m_sceneRect.roundedRect)
|
||||||
{
|
{
|
||||||
m_renderTarget->DrawRoundedRectangle(m_sceneRect.roundedRect.value(), m_borderBrush.get(), static_cast<float>(m_sceneRect.thickness * 2));
|
m_renderTarget->DrawRoundedRectangle(m_sceneRect.roundedRect.value(), m_borderBrush.get(), static_cast<float>(m_sceneRect.thickness));
|
||||||
}
|
}
|
||||||
else if (m_sceneRect.rect)
|
else if (m_sceneRect.rect)
|
||||||
{
|
{
|
||||||
m_renderTarget->DrawRectangle(m_sceneRect.rect.value(), m_borderBrush.get(), static_cast<float>(m_sceneRect.thickness * 2));
|
m_renderTarget->DrawRectangle(m_sceneRect.rect.value(), m_borderBrush.get(), static_cast<float>(m_sceneRect.thickness));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_renderTarget->EndDraw();
|
m_renderTarget->EndDraw();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public:
|
|||||||
|
|
||||||
void Show();
|
void Show();
|
||||||
void Hide();
|
void Hide();
|
||||||
void SetBorderRect(RECT windowRect, COLORREF color, int thickness, int radius);
|
void SetBorderRect(RECT windowRect, COLORREF color, int thickness, float radius);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CreateRenderTargets(const RECT& clientRect);
|
bool CreateRenderTargets(const RECT& clientRect);
|
||||||
@@ -34,7 +34,7 @@ private:
|
|||||||
static ID2D1Factory* GetD2DFactory();
|
static ID2D1Factory* GetD2DFactory();
|
||||||
static IDWriteFactory* GetWriteFactory();
|
static IDWriteFactory* GetWriteFactory();
|
||||||
static D2D1_COLOR_F ConvertColor(COLORREF color);
|
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);
|
static D2D1_RECT_F ConvertRect(RECT rect, int thickness);
|
||||||
void Render();
|
void Render();
|
||||||
|
|
||||||
|
|||||||
19
src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.cpp
Normal file
19
src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.cpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "ScalingUtils.h"
|
||||||
|
|
||||||
|
#include <common/Display/dpi_aware.h>
|
||||||
|
#include <common/utils/winapi_error.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
6
src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.h
Normal file
6
src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ScalingUtils
|
||||||
|
{
|
||||||
|
float ScalingFactor(HWND window) noexcept;
|
||||||
|
};
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "winrt/Windows.Foundation.h"
|
#include "winrt/Windows.Foundation.h"
|
||||||
|
|
||||||
#include <FrameDrawer.h>
|
#include <FrameDrawer.h>
|
||||||
|
#include <ScalingUtils.h>
|
||||||
#include <Settings.h>
|
#include <Settings.h>
|
||||||
#include <WindowCornersUtil.h>
|
#include <WindowCornersUtil.h>
|
||||||
|
|
||||||
@@ -192,13 +193,15 @@ void WindowBorder::UpdateBorderProperties() const
|
|||||||
color = AlwaysOnTopSettings::settings().frameColor;
|
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)
|
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<int>(thickness), cornerRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT WindowBorder::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept
|
LRESULT WindowBorder::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ enum DWM_WINDOW_CORNER_PREFERENCE
|
|||||||
DWMWCP_ROUNDSMALL = 3
|
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));
|
auto res = DwmGetWindowAttribute(window, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPreference, sizeof(cornerPreference));
|
||||||
if (res != S_OK)
|
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));
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
namespace WindowBordersUtils
|
namespace WindowCornerUtils
|
||||||
{
|
{
|
||||||
bool AreCornersRounded(HWND window) noexcept;
|
int CornerPreference(HWND window) noexcept;
|
||||||
|
int CornersRadius(HWND window) noexcept;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user