Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/modules/fancyzones/FancyZonesLib/FancyZones.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,14 @@ void FancyZones::UpdateWorkAreas(bool updateWindowPositions) noexcept
std::vector<FancyZonesDataTypes::MonitorId> monitors = { FancyZonesDataTypes::MonitorId{ .monitor = nullptr, .deviceId = { .id = ZonedWindowProperties::MultiMonitorName, .instanceId = ZonedWindowProperties::MultiMonitorInstance } } };
if (ShouldWorkAreasBeRecreated(monitors, currentVirtualDesktop, m_workAreaConfiguration.GetAllWorkAreas()))
{
// WindowMouseSnap caches a raw WorkArea* in m_currentWorkArea and the
// WorkArea map by reference. WorkAreaConfiguration::Clear() destroys
// every unique_ptr<WorkArea> (and hence the inner ZonesOverlay and
// its std::mutex). If a drag is in flight, the next MoveSizeUpdate
// would dereference that dangling WorkArea* and lock the freed
// mutex. Drain the active drag first so subsequent drag messages
// hit the snapper's `if (m_windowMouseSnapper)` guard and no-op.
MoveSizeEnd();
m_workAreaConfiguration.Clear();

FancyZonesDataTypes::WorkAreaId workAreaId;
Expand All @@ -853,6 +861,8 @@ void FancyZones::UpdateWorkAreas(bool updateWindowPositions) noexcept

if (ShouldWorkAreasBeRecreated(monitors, currentVirtualDesktop, workAreas))
{
// See comment above the matching Clear() in the span-zones branch.
MoveSizeEnd();
m_workAreaConfiguration.Clear();
for (const auto& monitor : monitors)
{
Expand Down Expand Up @@ -1065,6 +1075,9 @@ void FancyZones::SettingsUpdate(SettingId id)
break;
case SettingId::SpanZonesAcrossMonitors:
{
// See UpdateWorkAreas() — same WindowMouseSnap dangling-WorkArea*
// hazard if the user toggles this setting mid-drag.
MoveSizeEnd();
m_workAreaConfiguration.Clear();
PostMessageW(m_window, WM_PRIV_INIT, NULL, NULL);
}
Expand Down
9 changes: 8 additions & 1 deletion src/modules/fancyzones/FancyZonesLib/OnThreadExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,14 @@ void OnThreadExecutor::worker_thread()

OnThreadExecutor::~OnThreadExecutor()
{
_shutdown_request = true;
{
// Modify the shared shutdown flag while holding the mutex so the
// worker reliably observes it on its next wake. Without this, a notify
// racing the worker entering _task_cv.wait can be missed and the join
// below hangs forever.
std::lock_guard lock{ _task_mutex };
_shutdown_request = true;
}
_task_cv.notify_one();
_worker_thread.join();
}
5 changes: 5 additions & 0 deletions src/modules/fancyzones/FancyZonesLib/WorkArea.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ WorkArea::WorkArea(HINSTANCE hinstance, const FancyZonesDataTypes::WorkAreaId& u

WorkArea::~WorkArea()
{
// Tear down the renderer (joining its background thread) before returning
// the HWND to the pool. Otherwise, the render thread can still be drawing
// through m_renderTarget into an HWND that has already been recycled by a
// subsequent NewZonesOverlayWindow call.
m_zonesOverlay.reset();
windowPool.FreeZonesOverlayWindow(m_window);
}

Expand Down
16 changes: 11 additions & 5 deletions src/modules/fancyzones/FancyZonesLib/ZonesOverlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,19 @@ void ZonesOverlay::DrawActiveZoneSet(const ZonesMap& zones,

ZonesOverlay::~ZonesOverlay()
{
// Constructor early-returns (e.g. CreateHwndRenderTarget failing during a
// display-driver TDR) leave m_renderThread default-constructed; calling
// join() on a non-joinable thread terminates the process.
if (m_renderThread.joinable())
{
std::unique_lock lock(m_mutex);
m_abortThread = true;
m_shouldRender = true;
{
std::unique_lock lock(m_mutex);
m_abortThread = true;
m_shouldRender = true;
}
m_cv.notify_all();
m_renderThread.join();
}
m_cv.notify_all();
m_renderThread.join();

if (m_renderTarget)
{
Expand Down
Loading