mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-06 19:26:39 +02:00
[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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user