mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
[FancyZones]Fix moving windows on other virtual desktops (#29059)
* clean up obsolete vd check * clean up * replace virtual desktop id usage * check current vd
This commit is contained in:
@@ -156,9 +156,9 @@ private:
|
||||
void SyncVirtualDesktops() noexcept;
|
||||
|
||||
void UpdateHotkey(int hotkeyId, const PowerToysSettings::HotkeyObject& hotkeyObject, bool enable) noexcept;
|
||||
|
||||
bool MoveToAppLastZone(HWND window, HMONITOR monitor) noexcept;
|
||||
|
||||
bool MoveToAppLastZone(HWND window, HMONITOR monitor, GUID currentVirtualDesktop) noexcept;
|
||||
|
||||
void RefreshLayouts() noexcept;
|
||||
bool ShouldProcessSnapHotkey(DWORD vkCode) noexcept;
|
||||
void ApplyQuickLayout(int key) noexcept;
|
||||
@@ -257,7 +257,6 @@ FancyZones::Run() noexcept
|
||||
}
|
||||
});
|
||||
|
||||
VirtualDesktop::instance().UpdateVirtualDesktopId();
|
||||
SyncVirtualDesktops();
|
||||
|
||||
// id format of applied-layouts and app-zone-history was changed in 0.60
|
||||
@@ -332,7 +331,7 @@ void FancyZones::MoveSizeEnd()
|
||||
}
|
||||
}
|
||||
|
||||
bool FancyZones::MoveToAppLastZone(HWND window, HMONITOR monitor) noexcept
|
||||
bool FancyZones::MoveToAppLastZone(HWND window, HMONITOR monitor, GUID currentVirtualDesktop) noexcept
|
||||
{
|
||||
const auto& workAreas = m_workAreaConfiguration.GetAllWorkAreas();
|
||||
WorkArea* workArea{ nullptr };
|
||||
@@ -343,7 +342,7 @@ bool FancyZones::MoveToAppLastZone(HWND window, HMONITOR monitor) noexcept
|
||||
if (workAreas.contains(monitor))
|
||||
{
|
||||
workArea = workAreas.at(monitor).get();
|
||||
if (workArea)
|
||||
if (workArea && workArea->UniqueId().virtualDesktopId == currentVirtualDesktop)
|
||||
{
|
||||
indexes = AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workArea->UniqueId(), workArea->GetLayoutId());
|
||||
}
|
||||
@@ -357,7 +356,7 @@ bool FancyZones::MoveToAppLastZone(HWND window, HMONITOR monitor) noexcept
|
||||
{
|
||||
for (const auto& [_, secondaryWorkArea] : workAreas)
|
||||
{
|
||||
if (secondaryWorkArea)
|
||||
if (secondaryWorkArea && secondaryWorkArea->UniqueId().virtualDesktopId == currentVirtualDesktop)
|
||||
{
|
||||
indexes = AppZoneHistory::instance().GetAppLastZoneIndexSet(window, secondaryWorkArea->UniqueId(), secondaryWorkArea->GetLayoutId());
|
||||
workArea = secondaryWorkArea.get();
|
||||
@@ -412,27 +411,28 @@ void FancyZones::WindowCreated(HWND window) noexcept
|
||||
}
|
||||
|
||||
bool windowMovedToZone = false;
|
||||
auto currentVirtualDesktop = VirtualDesktop::instance().GetCurrentVirtualDesktopIdFromRegistry();
|
||||
if (moveToAppLastZone)
|
||||
{
|
||||
if (FancyZonesSettings::settings().spanZonesAcrossMonitors)
|
||||
{
|
||||
windowMovedToZone = MoveToAppLastZone(window, nullptr);
|
||||
windowMovedToZone = MoveToAppLastZone(window, nullptr, currentVirtualDesktop);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search application history on currently active monitor.
|
||||
windowMovedToZone = MoveToAppLastZone(window, active);
|
||||
windowMovedToZone = MoveToAppLastZone(window, active, currentVirtualDesktop);
|
||||
|
||||
if (!windowMovedToZone && primary != active)
|
||||
{
|
||||
// Search application history on primary monitor.
|
||||
windowMovedToZone = MoveToAppLastZone(window, primary);
|
||||
windowMovedToZone = MoveToAppLastZone(window, primary, currentVirtualDesktop);
|
||||
}
|
||||
|
||||
if (!windowMovedToZone)
|
||||
{
|
||||
// Search application history on remaining monitors.
|
||||
windowMovedToZone = MoveToAppLastZone(window, nullptr);
|
||||
windowMovedToZone = MoveToAppLastZone(window, nullptr, currentVirtualDesktop);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -641,12 +641,10 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
||||
}
|
||||
else if (message == WM_PRIV_INIT)
|
||||
{
|
||||
VirtualDesktop::instance().UpdateVirtualDesktopId();
|
||||
OnDisplayChange(DisplayChangeType::Initialization);
|
||||
}
|
||||
else if (message == WM_PRIV_VD_SWITCH)
|
||||
{
|
||||
VirtualDesktop::instance().UpdateVirtualDesktopId();
|
||||
OnDisplayChange(DisplayChangeType::VirtualDesktop);
|
||||
}
|
||||
else if (message == WM_PRIV_EDITOR)
|
||||
@@ -745,10 +743,10 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
||||
|
||||
bool FancyZones::AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id) noexcept
|
||||
{
|
||||
wil::unique_cotaskmem_string virtualDesktopIdStr;
|
||||
if (!SUCCEEDED(StringFromCLSID(VirtualDesktop::instance().GetCurrentVirtualDesktopId(), &virtualDesktopIdStr)))
|
||||
auto virtualDesktopIdStr = FancyZonesUtils::GuidToString(id.virtualDesktopId);
|
||||
if (virtualDesktopIdStr)
|
||||
{
|
||||
Logger::debug(L"Add new work area on virtual desktop {}", virtualDesktopIdStr.get());
|
||||
Logger::debug(L"Add new work area on virtual desktop {}", virtualDesktopIdStr.value());
|
||||
}
|
||||
|
||||
FancyZonesUtils::Rect rect{};
|
||||
@@ -794,11 +792,12 @@ void FancyZones::UpdateWorkAreas(bool updateWindowPositions) noexcept
|
||||
Logger::debug(L"Update work areas, update windows positions: {}", updateWindowPositions);
|
||||
|
||||
m_workAreaConfiguration.Clear();
|
||||
auto currentVirtualDesktop = VirtualDesktop::instance().GetCurrentVirtualDesktopIdFromRegistry();
|
||||
|
||||
if (FancyZonesSettings::settings().spanZonesAcrossMonitors)
|
||||
{
|
||||
FancyZonesDataTypes::WorkAreaId workAreaId;
|
||||
workAreaId.virtualDesktopId = VirtualDesktop::instance().GetCurrentVirtualDesktopId();
|
||||
workAreaId.virtualDesktopId = currentVirtualDesktop;
|
||||
workAreaId.monitorId = { .deviceId = { .id = ZonedWindowProperties::MultiMonitorName, .instanceId = ZonedWindowProperties::MultiMonitorInstance } };
|
||||
|
||||
AddWorkArea(nullptr, workAreaId);
|
||||
@@ -809,7 +808,7 @@ void FancyZones::UpdateWorkAreas(bool updateWindowPositions) noexcept
|
||||
for (const auto& monitor : monitors)
|
||||
{
|
||||
FancyZonesDataTypes::WorkAreaId workAreaId;
|
||||
workAreaId.virtualDesktopId = VirtualDesktop::instance().GetCurrentVirtualDesktopId();
|
||||
workAreaId.virtualDesktopId = currentVirtualDesktop;
|
||||
workAreaId.monitorId = monitor;
|
||||
|
||||
AddWorkArea(monitor.monitor, workAreaId);
|
||||
@@ -906,7 +905,7 @@ void FancyZones::SyncVirtualDesktops() noexcept
|
||||
// that case (00000000-0000-0000-0000-000000000000).
|
||||
|
||||
auto lastUsed = LastUsedVirtualDesktop::instance().GetId();
|
||||
auto current = VirtualDesktop::instance().GetCurrentVirtualDesktopId();
|
||||
auto current = VirtualDesktop::instance().GetCurrentVirtualDesktopIdFromRegistry();
|
||||
auto guids = VirtualDesktop::instance().GetVirtualDesktopIdsFromRegistry();
|
||||
|
||||
if (current != lastUsed)
|
||||
|
||||
@@ -278,32 +278,7 @@ void AppZoneHistory::LoadData()
|
||||
|
||||
void AppZoneHistory::SaveData()
|
||||
{
|
||||
bool dirtyFlag = false;
|
||||
std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>> updatedHistory;
|
||||
|
||||
for (const auto& [path, dataVector] : m_history)
|
||||
{
|
||||
auto updatedVector = dataVector;
|
||||
for (auto& data : updatedVector)
|
||||
{
|
||||
if (!VirtualDesktop::instance().IsVirtualDesktopIdSavedInRegistry(data.workAreaId.virtualDesktopId))
|
||||
{
|
||||
data.workAreaId.virtualDesktopId = GUID_NULL;
|
||||
dirtyFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
updatedHistory.insert(std::make_pair(path, updatedVector));
|
||||
}
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
json::to_file(AppZoneHistoryFileName(), JsonUtils::SerializeJson(updatedHistory));
|
||||
}
|
||||
else
|
||||
{
|
||||
json::to_file(AppZoneHistoryFileName(), JsonUtils::SerializeJson(m_history));
|
||||
}
|
||||
json::to_file(AppZoneHistoryFileName(), JsonUtils::SerializeJson(m_history));
|
||||
}
|
||||
|
||||
void AppZoneHistory::AdjustWorkAreaIds(const std::vector<FancyZonesDataTypes::MonitorId>& ids)
|
||||
|
||||
@@ -96,14 +96,14 @@ VirtualDesktop& VirtualDesktop::instance()
|
||||
return self;
|
||||
}
|
||||
|
||||
std::optional<GUID> VirtualDesktop::GetCurrentVirtualDesktopIdFromRegistry() const
|
||||
GUID VirtualDesktop::GetCurrentVirtualDesktopIdFromRegistry() const
|
||||
{
|
||||
// On newer Windows builds, the current virtual desktop is persisted to
|
||||
// a totally different reg key. Look there first.
|
||||
std::optional<GUID> desktopId = NewGetCurrentDesktopId();
|
||||
if (desktopId.has_value())
|
||||
{
|
||||
return desktopId;
|
||||
return desktopId.value();
|
||||
}
|
||||
|
||||
// Explorer persists current virtual desktop identifier to registry on a per session basis, but only
|
||||
@@ -112,7 +112,7 @@ std::optional<GUID> VirtualDesktop::GetCurrentVirtualDesktopIdFromRegistry() con
|
||||
desktopId = GetDesktopIdFromCurrentSession();
|
||||
if (desktopId.has_value())
|
||||
{
|
||||
return desktopId;
|
||||
return desktopId.value();
|
||||
}
|
||||
|
||||
// Fallback scenario is to get array of virtual desktops stored in registry, but not kept per session.
|
||||
@@ -128,7 +128,7 @@ std::optional<GUID> VirtualDesktop::GetCurrentVirtualDesktopIdFromRegistry() con
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return GUID_NULL;
|
||||
}
|
||||
|
||||
std::optional<std::vector<GUID>> VirtualDesktop::GetVirtualDesktopIdsFromRegistry(HKEY hKey) const
|
||||
@@ -169,25 +169,6 @@ std::optional<std::vector<GUID>> VirtualDesktop::GetVirtualDesktopIdsFromRegistr
|
||||
return GetVirtualDesktopIdsFromRegistry(GetVirtualDesktopsRegKey());
|
||||
}
|
||||
|
||||
bool VirtualDesktop::IsVirtualDesktopIdSavedInRegistry(GUID id) const
|
||||
{
|
||||
auto ids = GetVirtualDesktopIdsFromRegistry();
|
||||
if (!ids.has_value())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& regId : *ids)
|
||||
{
|
||||
if (regId == id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VirtualDesktop::IsWindowOnCurrentDesktop(HWND window) const
|
||||
{
|
||||
BOOL isWindowOnCurrentDesktop = false;
|
||||
@@ -199,47 +180,6 @@ bool VirtualDesktop::IsWindowOnCurrentDesktop(HWND window) const
|
||||
return isWindowOnCurrentDesktop;
|
||||
}
|
||||
|
||||
std::optional<GUID> VirtualDesktop::GetDesktopId(HWND window) const
|
||||
{
|
||||
GUID id;
|
||||
BOOL isWindowOnCurrentDesktop = false;
|
||||
if (m_vdManager && m_vdManager->IsWindowOnCurrentVirtualDesktop(window, &isWindowOnCurrentDesktop) == S_OK && isWindowOnCurrentDesktop)
|
||||
{
|
||||
// Filter windows such as Windows Start Menu, Task Switcher, etc.
|
||||
if (m_vdManager->GetWindowDesktopId(window, &id) == S_OK)
|
||||
{
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<std::pair<HWND, GUID>> VirtualDesktop::GetWindowsRelatedToDesktops() const
|
||||
{
|
||||
using result_t = std::vector<HWND>;
|
||||
result_t windows;
|
||||
|
||||
auto callback = [](HWND window, LPARAM data) -> BOOL {
|
||||
result_t& result = *reinterpret_cast<result_t*>(data);
|
||||
result.push_back(window);
|
||||
return TRUE;
|
||||
};
|
||||
EnumWindows(callback, reinterpret_cast<LPARAM>(&windows));
|
||||
|
||||
std::vector<std::pair<HWND, GUID>> result;
|
||||
for (auto window : windows)
|
||||
{
|
||||
auto desktop = GetDesktopId(window);
|
||||
if (desktop.has_value())
|
||||
{
|
||||
result.push_back({ window, *desktop });
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<HWND> VirtualDesktop::GetWindowsFromCurrentDesktop() const
|
||||
{
|
||||
using result_t = std::vector<HWND>;
|
||||
@@ -263,49 +203,4 @@ std::vector<HWND> VirtualDesktop::GetWindowsFromCurrentDesktop() const
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GUID VirtualDesktop::GetCurrentVirtualDesktopId() const noexcept
|
||||
{
|
||||
return m_currentVirtualDesktopId;
|
||||
}
|
||||
|
||||
void VirtualDesktop::UpdateVirtualDesktopId() noexcept
|
||||
{
|
||||
auto currentVirtualDesktopId = GetCurrentVirtualDesktopIdFromRegistry();
|
||||
if (currentVirtualDesktopId.has_value())
|
||||
{
|
||||
m_currentVirtualDesktopId = currentVirtualDesktopId.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currentVirtualDesktopId = GUID_NULL;
|
||||
}
|
||||
|
||||
Trace::VirtualDesktopChanged();
|
||||
}
|
||||
|
||||
std::optional<GUID> VirtualDesktop::GetDesktopIdByTopLevelWindows() const
|
||||
{
|
||||
using result_t = std::vector<HWND>;
|
||||
result_t windows;
|
||||
|
||||
auto callback = [](HWND window, LPARAM data) -> BOOL {
|
||||
result_t& result = *reinterpret_cast<result_t*>(data);
|
||||
result.push_back(window);
|
||||
return TRUE;
|
||||
};
|
||||
EnumWindows(callback, reinterpret_cast<LPARAM>(&windows));
|
||||
|
||||
for (const auto window : windows)
|
||||
{
|
||||
std::optional<GUID> id = GetDesktopId(window);
|
||||
if (id.has_value())
|
||||
{
|
||||
// Otherwise keep checking other windows
|
||||
return *id;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
@@ -5,29 +5,19 @@ class VirtualDesktop
|
||||
public:
|
||||
static VirtualDesktop& instance();
|
||||
|
||||
// saved values
|
||||
GUID GetCurrentVirtualDesktopId() const noexcept;
|
||||
void UpdateVirtualDesktopId() noexcept;
|
||||
|
||||
// IVirtualDesktopManager
|
||||
bool IsWindowOnCurrentDesktop(HWND window) const;
|
||||
std::optional<GUID> GetDesktopId(HWND window) const;
|
||||
std::optional<GUID> GetDesktopIdByTopLevelWindows() const;
|
||||
std::vector<std::pair<HWND, GUID>> GetWindowsRelatedToDesktops() const;
|
||||
std::vector<HWND> GetWindowsFromCurrentDesktop() const;
|
||||
|
||||
// registry
|
||||
std::optional<GUID> GetCurrentVirtualDesktopIdFromRegistry() const;
|
||||
GUID GetCurrentVirtualDesktopIdFromRegistry() const;
|
||||
std::optional<std::vector<GUID>> GetVirtualDesktopIdsFromRegistry() const;
|
||||
bool IsVirtualDesktopIdSavedInRegistry(GUID id) const;
|
||||
|
||||
|
||||
private:
|
||||
VirtualDesktop();
|
||||
~VirtualDesktop();
|
||||
|
||||
IVirtualDesktopManager* m_vdManager{nullptr};
|
||||
|
||||
GUID m_currentVirtualDesktopId{};
|
||||
|
||||
std::optional<std::vector<GUID>> GetVirtualDesktopIdsFromRegistry(HKEY hKey) const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user