[FancyZones] Open window in a zone fix (#18193)

* removed background thread monitoring virtual desktops

* removed virtual desktop callbacks

* centralize work with virtual desktops

* updated virtual desktops sync

* app zone history logs

* logs

* get uwp process path

* spell
This commit is contained in:
Seraphima Zykova
2022-05-13 15:06:11 +02:00
committed by GitHub
parent d15ff6da8d
commit 5f4a26ebba
11 changed files with 256 additions and 249 deletions

View File

@@ -8,6 +8,7 @@
#include <FancyZonesLib/GuidUtils.h>
#include <FancyZonesLib/FancyZonesWindowProperties.h>
#include <FancyZonesLib/JsonHelpers.h>
#include <FancyZonesLib/VirtualDesktop.h>
#include <FancyZonesLib/util.h>
namespace JsonUtils
@@ -221,11 +222,6 @@ AppZoneHistory& AppZoneHistory::instance()
return self;
}
void AppZoneHistory::SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback)
{
m_virtualDesktopCheckCallback = callback;
}
void AppZoneHistory::LoadData()
{
auto file = AppZoneHistoryFileName();
@@ -253,22 +249,20 @@ void AppZoneHistory::SaveData()
{
bool dirtyFlag = false;
std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>> updatedHistory;
if (m_virtualDesktopCheckCallback)
for (const auto& [path, dataVector] : m_history)
{
for (const auto& [path, dataVector] : m_history)
auto updatedVector = dataVector;
for (auto& data : updatedVector)
{
auto updatedVector = dataVector;
for (auto& data : updatedVector)
if (!VirtualDesktop::instance().IsVirtualDesktopIdSavedInRegistry(data.deviceId.virtualDesktopId))
{
if (!m_virtualDesktopCheckCallback(data.deviceId.virtualDesktopId))
{
data.deviceId.virtualDesktopId = GUID_NULL;
dirtyFlag = true;
}
data.deviceId.virtualDesktopId = GUID_NULL;
dirtyFlag = true;
}
updatedHistory.insert(std::make_pair(path, updatedVector));
}
updatedHistory.insert(std::make_pair(path, updatedVector));
}
if (dirtyFlag)
@@ -288,7 +282,7 @@ bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::Dev
return false;
}
auto processPath = get_process_path(window);
auto processPath = get_process_path_waiting_uwp(window);
if (processPath.empty())
{
return false;
@@ -343,7 +337,7 @@ bool AppZoneHistory::RemoveAppLastZone(HWND window, const FancyZonesDataTypes::D
{
Logger::info(L"Add app zone history, device: {}, layout: {}", deviceId.toString(), zoneSetId);
auto processPath = get_process_path(window);
auto processPath = get_process_path_waiting_uwp(window);
if (!processPath.empty())
{
auto history = m_history.find(processPath);
@@ -404,25 +398,50 @@ const AppZoneHistory::TAppZoneHistoryMap& AppZoneHistory::GetFullAppZoneHistory(
std::optional<FancyZonesDataTypes::AppZoneHistoryData> AppZoneHistory::GetZoneHistory(const std::wstring& appPath, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept
{
auto iter = m_history.find(appPath);
if (iter != m_history.end())
auto app = appPath;
auto pos = appPath.find_last_of('\\');
if (pos != std::string::npos && pos + 1 < appPath.length())
{
auto historyVector = iter->second;
for (const auto& history : historyVector)
app = appPath.substr(pos + 1);
}
auto srcVirtualDesktopIDStr = FancyZonesUtils::GuidToString(deviceId.virtualDesktopId);
if (srcVirtualDesktopIDStr)
{
Logger::debug(L"Get {} zone history on monitor: {}, virtual desktop: {}", app, deviceId.deviceName, srcVirtualDesktopIDStr.value());
}
auto iter = m_history.find(appPath);
if (iter == m_history.end())
{
Logger::info("App history not found");
return std::nullopt;
}
auto historyVector = iter->second;
for (const auto& history : historyVector)
{
if (history.deviceId.deviceName == deviceId.deviceName)
{
if (history.deviceId == deviceId)
auto vdStr = FancyZonesUtils::GuidToString(history.deviceId.virtualDesktopId);
if (vdStr)
{
Logger::debug(L"App zone history found on the device {} with virtual desktop {}", history.deviceId.deviceName, vdStr.value());
}
if (history.deviceId.virtualDesktopId == deviceId.virtualDesktopId || history.deviceId.virtualDesktopId == GUID_NULL)
{
return history;
}
}
}
return std::nullopt;
}
bool AppZoneHistory::IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept
{
auto processPath = get_process_path(window);
auto processPath = get_process_path_waiting_uwp(window);
if (!processPath.empty())
{
auto history = m_history.find(processPath);
@@ -456,7 +475,7 @@ bool AppZoneHistory::IsAnotherWindowOfApplicationInstanceZoned(HWND window, cons
void AppZoneHistory::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId)
{
auto processPath = get_process_path(window);
auto processPath = get_process_path_waiting_uwp(window);
if (!processPath.empty())
{
auto history = m_history.find(processPath);
@@ -479,39 +498,75 @@ void AppZoneHistory::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDat
ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const
{
auto processPath = get_process_path(window);
if (!processPath.empty())
auto processPath = get_process_path_waiting_uwp(window);
if (processPath.empty())
{
auto history = m_history.find(processPath);
if (history != std::end(m_history))
Logger::error("Process path is empty");
return {};
}
auto srcVirtualDesktopIDStr = FancyZonesUtils::GuidToString(deviceId.virtualDesktopId);
auto app = processPath;
auto pos = processPath.find_last_of('\\');
if (pos != std::string::npos && pos + 1 < processPath.length())
{
app = processPath.substr(pos + 1);
}
if (srcVirtualDesktopIDStr)
{
Logger::debug(L"Get {} zone history on monitor: {}, virtual desktop: {}", app, deviceId.deviceName, srcVirtualDesktopIDStr.value());
}
auto history = m_history.find(processPath);
if (history == std::end(m_history))
{
return {};
}
const auto& perDesktopData = history->second;
for (const auto& data : perDesktopData)
{
if (data.zoneSetUuid == zoneSetId && data.deviceId.deviceName == deviceId.deviceName)
{
const auto& perDesktopData = history->second;
for (const auto& data : perDesktopData)
auto vdStr = FancyZonesUtils::GuidToString(data.deviceId.virtualDesktopId);
if (vdStr)
{
if (data.zoneSetUuid == zoneSetId && data.deviceId == deviceId)
{
return data.zoneIndexSet;
}
Logger::debug(L"App zone history found on the device {} with virtual desktop {}", data.deviceId.deviceName, vdStr.value());
}
if (data.deviceId.virtualDesktopId == deviceId.virtualDesktopId || data.deviceId.virtualDesktopId == GUID_NULL)
{
return data.zoneIndexSet;
}
}
}
return {};
}
void AppZoneHistory::SyncVirtualDesktops(GUID currentVirtualDesktopId)
void AppZoneHistory::SyncVirtualDesktops()
{
// Explorer persists current virtual desktop identifier to registry on a per session basis,
// but only after first virtual desktop switch happens. If the user hasn't switched virtual
// desktops in this session value in registry will be empty and we will use default GUID in
// that case (00000000-0000-0000-0000-000000000000).
auto currentVirtualDesktopStr = FancyZonesUtils::GuidToString(currentVirtualDesktopId);
if (currentVirtualDesktopStr)
auto savedInRegistryVirtualDesktopID = VirtualDesktop::instance().GetCurrentVirtualDesktopIdFromRegistry();
if (!savedInRegistryVirtualDesktopID.has_value() || savedInRegistryVirtualDesktopID.value() == GUID_NULL)
{
Logger::info(L"AppZoneHistory Sync virtual desktops: current {}", currentVirtualDesktopStr.value());
return;
}
auto currentVirtualDesktopStr = FancyZonesUtils::GuidToString(savedInRegistryVirtualDesktopID.value());
if (!currentVirtualDesktopStr.has_value())
{
Logger::error(L"Failed to convert virtual desktop GUID to string");
return;
}
Logger::info(L"AppZoneHistory Sync virtual desktops: current {}", currentVirtualDesktopStr.value());
bool dirtyFlag = false;
for (auto& [path, perDesktopData] : m_history)
@@ -520,28 +575,15 @@ void AppZoneHistory::SyncVirtualDesktops(GUID currentVirtualDesktopId)
{
if (data.deviceId.virtualDesktopId == GUID_NULL)
{
data.deviceId.virtualDesktopId = currentVirtualDesktopId;
data.deviceId.virtualDesktopId = savedInRegistryVirtualDesktopID.value();
dirtyFlag = true;
}
else
{
if (m_virtualDesktopCheckCallback && !m_virtualDesktopCheckCallback(data.deviceId.virtualDesktopId))
{
data.deviceId.virtualDesktopId = GUID_NULL;
dirtyFlag = true;
}
}
}
}
if (dirtyFlag)
{
wil::unique_cotaskmem_string virtualDesktopIdStr;
if (SUCCEEDED(StringFromCLSID(currentVirtualDesktopId, &virtualDesktopIdStr)))
{
Logger::info(L"Update Virtual Desktop id to {}", virtualDesktopIdStr.get());
}
Logger::info(L"Update Virtual Desktop id to {}", currentVirtualDesktopStr.value());
SaveData();
}
}

View File

@@ -52,8 +52,7 @@ public:
void UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId);
ZoneIndexSet GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const;
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
void SyncVirtualDesktops(GUID currentVirtualDesktopId);
void SyncVirtualDesktops();
void RemoveDeletedVirtualDesktops(const std::vector<GUID>& activeDesktops);
private:
@@ -61,5 +60,4 @@ private:
~AppZoneHistory() = default;
TAppZoneHistoryMap m_history;
std::function<bool(GUID)> m_virtualDesktopCheckCallback;
};

View File

@@ -9,6 +9,7 @@
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
#include <FancyZonesLib/JsonHelpers.h>
#include <FancyZonesLib/VirtualDesktop.h>
#include <FancyZonesLib/util.h>
namespace
@@ -244,19 +245,17 @@ void AppliedLayouts::SaveData()
{
bool dirtyFlag = false;
TAppliedLayoutsMap updatedMap;
if (m_virtualDesktopCheckCallback)
for (const auto& [id, data] : m_layouts)
{
for (const auto& [id, data] : m_layouts)
auto updatedId = id;
if (!VirtualDesktop::instance().IsVirtualDesktopIdSavedInRegistry(id.virtualDesktopId))
{
auto updatedId = id;
if (!m_virtualDesktopCheckCallback(id.virtualDesktopId))
{
updatedId.virtualDesktopId = GUID_NULL;
dirtyFlag = true;
}
updatedMap.insert({ updatedId, data });
updatedId.virtualDesktopId = GUID_NULL;
dirtyFlag = true;
}
updatedMap.insert({ updatedId, data });
}
if (dirtyFlag)
@@ -269,28 +268,31 @@ void AppliedLayouts::SaveData()
}
}
void AppliedLayouts::SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback)
{
m_virtualDesktopCheckCallback = callback;
}
void AppliedLayouts::SyncVirtualDesktops(GUID currentVirtualDesktopId)
void AppliedLayouts::SyncVirtualDesktops()
{
// Explorer persists current virtual desktop identifier to registry on a per session basis,
// but only after first virtual desktop switch happens. If the user hasn't switched virtual
// desktops in this session value in registry will be empty and we will use default GUID in
// that case (00000000-0000-0000-0000-000000000000).
auto currentVirtualDesktopStr = FancyZonesUtils::GuidToString(currentVirtualDesktopId);
if (currentVirtualDesktopStr)
auto savedInRegistryVirtualDesktopID = VirtualDesktop::instance().GetCurrentVirtualDesktopIdFromRegistry();
if (!savedInRegistryVirtualDesktopID.has_value() || savedInRegistryVirtualDesktopID.value() == GUID_NULL)
{
Logger::info(L"AppliedLayouts Sync virtual desktops: current {}", currentVirtualDesktopStr.value());
}
return;
}
auto currentVirtualDesktopStr = FancyZonesUtils::GuidToString(savedInRegistryVirtualDesktopID.value());
if (!currentVirtualDesktopStr.has_value())
{
Logger::error(L"Failed to convert virtual desktop GUID to string");
return;
}
Logger::info(L"AppliedLayouts Sync virtual desktops: current {}", currentVirtualDesktopStr.value());
bool dirtyFlag = false;
std::vector<FancyZonesDataTypes::DeviceIdData> replaceWithCurrentId{};
std::vector<FancyZonesDataTypes::DeviceIdData> replaceWithNullId{};
for (const auto& [id, data] : m_layouts)
{
@@ -299,38 +301,18 @@ void AppliedLayouts::SyncVirtualDesktops(GUID currentVirtualDesktopId)
replaceWithCurrentId.push_back(id);
dirtyFlag = true;
}
else
{
if (m_virtualDesktopCheckCallback && !m_virtualDesktopCheckCallback(id.virtualDesktopId))
{
replaceWithNullId.push_back(id);
dirtyFlag = true;
}
}
}
for (const auto& id : replaceWithCurrentId)
{
auto mapEntry = m_layouts.extract(id);
mapEntry.key().virtualDesktopId = currentVirtualDesktopId;
m_layouts.insert(std::move(mapEntry));
}
for (const auto& id : replaceWithNullId)
{
auto mapEntry = m_layouts.extract(id);
mapEntry.key().virtualDesktopId = GUID_NULL;
mapEntry.key().virtualDesktopId = savedInRegistryVirtualDesktopID.value();
m_layouts.insert(std::move(mapEntry));
}
if (dirtyFlag)
{
wil::unique_cotaskmem_string virtualDesktopIdStr;
if (SUCCEEDED(StringFromCLSID(currentVirtualDesktopId, &virtualDesktopIdStr)))
{
Logger::info(L"Update Virtual Desktop id to {}", virtualDesktopIdStr.get());
}
Logger::info(L"Update Virtual Desktop id to {}", currentVirtualDesktopStr.value());
SaveData();
}
}

View File

@@ -48,8 +48,7 @@ public:
void LoadData();
void SaveData();
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
void SyncVirtualDesktops(GUID currentVirtualDesktopId);
void SyncVirtualDesktops();
void RemoveDeletedVirtualDesktops(const std::vector<GUID>& activeDesktops);
std::optional<Layout> GetDeviceLayout(const FancyZonesDataTypes::DeviceIdData& id) const noexcept;
@@ -67,5 +66,4 @@ private:
std::unique_ptr<FileWatcher> m_fileWatcher;
TAppliedLayoutsMap m_layouts;
std::function<bool(GUID)> m_virtualDesktopCheckCallback;
};