mirror of
https://github.com/microsoft/PowerToys
synced 2025-09-02 23:45:11 +00:00
[FancyZones]Fix memory leak on work area change (#31561)
* fz memleak fix * rect comparison * filter out unnecessary work area recreation
This commit is contained in:
@@ -144,13 +144,14 @@ public:
|
|||||||
|
|
||||||
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
||||||
void OnDisplayChange(DisplayChangeType changeType) noexcept;
|
void OnDisplayChange(DisplayChangeType changeType) noexcept;
|
||||||
bool AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id) noexcept;
|
bool AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id, const FancyZonesUtils::Rect& rect) noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static LRESULT CALLBACK s_WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
static LRESULT CALLBACK s_WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateWorkAreas(bool updateWindowPositions) noexcept;
|
void UpdateWorkAreas(bool updateWindowPositions) noexcept;
|
||||||
|
bool ShouldWorkAreasBeRecreated(const std::vector<FancyZonesDataTypes::MonitorId>& monitors, const GUID& virtualDesktop, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& workAreas) noexcept;
|
||||||
void CycleWindows(bool reverse) noexcept;
|
void CycleWindows(bool reverse) noexcept;
|
||||||
|
|
||||||
void SyncVirtualDesktops() noexcept;
|
void SyncVirtualDesktops() noexcept;
|
||||||
@@ -741,7 +742,7 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
|||||||
UpdateWorkAreas(updateWindowsPositions);
|
UpdateWorkAreas(updateWindowsPositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FancyZones::AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id) noexcept
|
bool FancyZones::AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id, const FancyZonesUtils::Rect& rect) noexcept
|
||||||
{
|
{
|
||||||
auto virtualDesktopIdStr = FancyZonesUtils::GuidToString(id.virtualDesktopId);
|
auto virtualDesktopIdStr = FancyZonesUtils::GuidToString(id.virtualDesktopId);
|
||||||
if (virtualDesktopIdStr)
|
if (virtualDesktopIdStr)
|
||||||
@@ -749,16 +750,6 @@ bool FancyZones::AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAr
|
|||||||
Logger::debug(L"Add new work area on virtual desktop {}", virtualDesktopIdStr.value());
|
Logger::debug(L"Add new work area on virtual desktop {}", virtualDesktopIdStr.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
FancyZonesUtils::Rect rect{};
|
|
||||||
if (monitor)
|
|
||||||
{
|
|
||||||
rect = MonitorUtils::GetWorkAreaRect(monitor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rect = FancyZonesUtils::GetAllMonitorsCombinedRect<&MONITORINFO::rcWork>();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto parentWorkAreaId = id;
|
auto parentWorkAreaId = id;
|
||||||
parentWorkAreaId.virtualDesktopId = LastUsedVirtualDesktop::instance().GetId();
|
parentWorkAreaId.virtualDesktopId = LastUsedVirtualDesktop::instance().GetId();
|
||||||
|
|
||||||
@@ -791,27 +782,38 @@ void FancyZones::UpdateWorkAreas(bool updateWindowPositions) noexcept
|
|||||||
{
|
{
|
||||||
Logger::debug(L"Update work areas, update windows positions: {}", updateWindowPositions);
|
Logger::debug(L"Update work areas, update windows positions: {}", updateWindowPositions);
|
||||||
|
|
||||||
m_workAreaConfiguration.Clear();
|
|
||||||
auto currentVirtualDesktop = VirtualDesktop::instance().GetCurrentVirtualDesktopIdFromRegistry();
|
auto currentVirtualDesktop = VirtualDesktop::instance().GetCurrentVirtualDesktopIdFromRegistry();
|
||||||
|
|
||||||
if (FancyZonesSettings::settings().spanZonesAcrossMonitors)
|
if (FancyZonesSettings::settings().spanZonesAcrossMonitors)
|
||||||
{
|
{
|
||||||
FancyZonesDataTypes::WorkAreaId workAreaId;
|
std::vector<FancyZonesDataTypes::MonitorId> monitors = { FancyZonesDataTypes::MonitorId{ .monitor = nullptr, .deviceId = { .id = ZonedWindowProperties::MultiMonitorName, .instanceId = ZonedWindowProperties::MultiMonitorInstance } } };
|
||||||
workAreaId.virtualDesktopId = currentVirtualDesktop;
|
if (ShouldWorkAreasBeRecreated(monitors, currentVirtualDesktop, m_workAreaConfiguration.GetAllWorkAreas()))
|
||||||
workAreaId.monitorId = { .deviceId = { .id = ZonedWindowProperties::MultiMonitorName, .instanceId = ZonedWindowProperties::MultiMonitorInstance } };
|
{
|
||||||
|
m_workAreaConfiguration.Clear();
|
||||||
|
|
||||||
AddWorkArea(nullptr, workAreaId);
|
FancyZonesDataTypes::WorkAreaId workAreaId;
|
||||||
|
workAreaId.virtualDesktopId = currentVirtualDesktop;
|
||||||
|
workAreaId.monitorId = { .deviceId = { .id = ZonedWindowProperties::MultiMonitorName, .instanceId = ZonedWindowProperties::MultiMonitorInstance } };
|
||||||
|
|
||||||
|
AddWorkArea(nullptr, workAreaId, FancyZonesUtils::GetAllMonitorsCombinedRect<&MONITORINFO::rcWork>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto monitors = MonitorUtils::IdentifyMonitors();
|
auto monitors = MonitorUtils::IdentifyMonitors();
|
||||||
for (const auto& monitor : monitors)
|
const auto& workAreas = m_workAreaConfiguration.GetAllWorkAreas();
|
||||||
|
|
||||||
|
if (ShouldWorkAreasBeRecreated(monitors, currentVirtualDesktop, workAreas))
|
||||||
{
|
{
|
||||||
FancyZonesDataTypes::WorkAreaId workAreaId;
|
m_workAreaConfiguration.Clear();
|
||||||
workAreaId.virtualDesktopId = currentVirtualDesktop;
|
for (const auto& monitor : monitors)
|
||||||
workAreaId.monitorId = monitor;
|
{
|
||||||
|
FancyZonesDataTypes::WorkAreaId workAreaId;
|
||||||
|
workAreaId.virtualDesktopId = currentVirtualDesktop;
|
||||||
|
workAreaId.monitorId = monitor;
|
||||||
|
|
||||||
AddWorkArea(monitor.monitor, workAreaId);
|
AddWorkArea(monitor.monitor, workAreaId, MonitorUtils::GetWorkAreaRect(monitor.monitor));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -885,6 +887,52 @@ void FancyZones::UpdateWorkAreas(bool updateWindowPositions) noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FancyZones::ShouldWorkAreasBeRecreated(const std::vector<FancyZonesDataTypes::MonitorId>& monitors, const GUID& virtualDesktop, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& workAreas) noexcept
|
||||||
|
{
|
||||||
|
if (monitors.size() != workAreas.size())
|
||||||
|
{
|
||||||
|
Logger::trace(L"Monitor was added or removed");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& monitor : monitors)
|
||||||
|
{
|
||||||
|
auto iter = workAreas.find(monitor.monitor);
|
||||||
|
if (iter == workAreas.end())
|
||||||
|
{
|
||||||
|
Logger::trace(L"WorkArea not found");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter->second->UniqueId().monitorId.deviceId != monitor.deviceId)
|
||||||
|
{
|
||||||
|
Logger::trace(L"DeviceId changed");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter->second->UniqueId().monitorId.serialNumber != monitor.serialNumber)
|
||||||
|
{
|
||||||
|
Logger::trace(L"Serial number changed");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter->second->UniqueId().virtualDesktopId != virtualDesktop)
|
||||||
|
{
|
||||||
|
Logger::trace(L"Virtual desktop changed");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto rect = monitor.monitor ? MonitorUtils::GetWorkAreaRect(monitor.monitor) : FancyZonesUtils::Rect(FancyZonesUtils::GetMonitorsCombinedRect<&MONITORINFOEX::rcWork>(FancyZonesUtils::GetAllMonitorRects<&MONITORINFOEX::rcWork>()));
|
||||||
|
if (iter->second->GetWorkAreaRect() != rect)
|
||||||
|
{
|
||||||
|
Logger::trace(L"WorkArea size changed");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void FancyZones::CycleWindows(bool reverse) noexcept
|
void FancyZones::CycleWindows(bool reverse) noexcept
|
||||||
{
|
{
|
||||||
auto window = GetForegroundWindow();
|
auto window = GetForegroundWindow();
|
||||||
|
@@ -41,16 +41,6 @@ float ZonesOverlay::GetAnimationAlpha()
|
|||||||
return std::clamp(millis / FadeInDurationMillis, 0.001f, 1.f);
|
return std::clamp(millis / FadeInDurationMillis, 0.001f, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ID2D1Factory* ZonesOverlay::GetD2DFactory()
|
|
||||||
{
|
|
||||||
static auto pD2DFactory = [] {
|
|
||||||
ID2D1Factory* res = nullptr;
|
|
||||||
D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &res);
|
|
||||||
return res;
|
|
||||||
}();
|
|
||||||
return pD2DFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
IDWriteFactory* ZonesOverlay::GetWriteFactory()
|
IDWriteFactory* ZonesOverlay::GetWriteFactory()
|
||||||
{
|
{
|
||||||
static auto pDWriteFactory = [] {
|
static auto pDWriteFactory = [] {
|
||||||
@@ -99,7 +89,11 @@ ZonesOverlay::ZonesOverlay(HWND window)
|
|||||||
auto renderTargetSize = D2D1::SizeU(m_clientRect.right - m_clientRect.left, m_clientRect.bottom - m_clientRect.top);
|
auto renderTargetSize = D2D1::SizeU(m_clientRect.right - m_clientRect.left, m_clientRect.bottom - m_clientRect.top);
|
||||||
auto hwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(window, renderTargetSize);
|
auto hwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(window, renderTargetSize);
|
||||||
|
|
||||||
hr = GetD2DFactory()->CreateHwndRenderTarget(renderTargetProperties, hwndRenderTargetProperties, &m_renderTarget);
|
ID2D1Factory* factory = nullptr;
|
||||||
|
D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &factory);
|
||||||
|
hr = factory->CreateHwndRenderTarget(renderTargetProperties, hwndRenderTargetProperties, &m_renderTarget);
|
||||||
|
factory->Release();
|
||||||
|
factory = nullptr;
|
||||||
|
|
||||||
if (!SUCCEEDED(hr))
|
if (!SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
@@ -357,5 +351,6 @@ ZonesOverlay::~ZonesOverlay()
|
|||||||
if (m_renderTarget)
|
if (m_renderTarget)
|
||||||
{
|
{
|
||||||
m_renderTarget->Release();
|
m_renderTarget->Release();
|
||||||
|
m_renderTarget = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,6 @@ class ZonesOverlay
|
|||||||
std::vector<DrawableRect> m_sceneRects;
|
std::vector<DrawableRect> m_sceneRects;
|
||||||
|
|
||||||
float GetAnimationAlpha();
|
float GetAnimationAlpha();
|
||||||
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_RECT_F ConvertRect(RECT rect);
|
static D2D1_RECT_F ConvertRect(RECT rect);
|
||||||
|
@@ -34,6 +34,16 @@ namespace FancyZonesUtils
|
|||||||
RECT m_rect{};
|
RECT m_rect{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const FancyZonesUtils::Rect& left, const FancyZonesUtils::Rect& right)
|
||||||
|
{
|
||||||
|
return left.left() == right.left() && left.right() == right.right() && left.top() == right.top() && left.bottom() == right.bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const FancyZonesUtils::Rect& left, const FancyZonesUtils::Rect& right)
|
||||||
|
{
|
||||||
|
return left.left() != right.left() || left.right() != right.right() || left.top() != right.top() || left.bottom() != right.bottom();
|
||||||
|
}
|
||||||
|
|
||||||
inline void InitRGB(_Out_ RGBQUAD* quad, BYTE alpha, COLORREF color)
|
inline void InitRGB(_Out_ RGBQUAD* quad, BYTE alpha, COLORREF color)
|
||||||
{
|
{
|
||||||
ZeroMemory(quad, sizeof(*quad));
|
ZeroMemory(quad, sizeof(*quad));
|
||||||
|
Reference in New Issue
Block a user