diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index e932f4a57e..02f924ef05 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -9,6 +9,7 @@ #include "lib/JsonHelpers.h" #include "lib/ZoneSet.h" #include "trace.h" +#include "VirtualDesktopUtils.h" #include #include @@ -349,17 +350,28 @@ FancyZones::VirtualDesktopInitialize() noexcept IFACEMETHODIMP_(void) FancyZones::WindowCreated(HWND window) noexcept { + std::shared_lock readLock(m_lock); if (m_settings->GetSettings()->appLastZone_moveWindows && IsInterestingWindow(window)) { for (const auto& [monitor, zoneWindow] : m_zoneWindowMap) { + // WindowCreated is also invoked when a virtual desktop switch occurs, we need a way + // to figure out when that happens to avoid moving windows that should not be moved. + GUID windowDesktopId{}; + GUID zoneWindowDesktopId{}; + if (VirtualDesktopUtils::GetWindowDesktopId(window, &windowDesktopId) && + VirtualDesktopUtils::GetZoneWindowDesktopId(zoneWindow.get(), &zoneWindowDesktopId) && + (windowDesktopId != zoneWindowDesktopId)) + { + return; + } const auto activeZoneSet = zoneWindow->ActiveZoneSet(); if (activeZoneSet) { const auto& fancyZonesData = JSONHelpers::FancyZonesDataInstance(); wil::unique_cotaskmem_string guidString; - if (SUCCEEDED_LOG(StringFromCLSID(activeZoneSet->Id(), &guidString))) + if (SUCCEEDED(StringFromCLSID(activeZoneSet->Id(), &guidString))) { int zoneIndex = fancyZonesData.GetAppLastZoneIndex(window, zoneWindow->UniqueId(), guidString.get()); if (zoneIndex != -1) diff --git a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj index 79366dc95c..ee090a28ab 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj @@ -103,6 +103,7 @@ + @@ -117,6 +118,7 @@ + diff --git a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters index 7478f922f8..af912e3803 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters @@ -48,6 +48,9 @@ Header Files + + Header Files + @@ -77,6 +80,9 @@ Source Files + + Source Files + diff --git a/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp b/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp new file mode 100644 index 0000000000..1a8e892854 --- /dev/null +++ b/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp @@ -0,0 +1,49 @@ +#include "pch.h" + +#include "VirtualDesktopUtils.h" + +namespace VirtualDesktopUtils +{ + const CLSID CLSID_ImmersiveShell = { 0xC2F03A33, 0x21F5, 0x47FA, 0xB4, 0xBB, 0x15, 0x63, 0x62, 0xA2, 0xF2, 0x39 }; + const wchar_t GUID_EmptyGUID[] = L"{00000000-0000-0000-0000-000000000000}"; + + IServiceProvider* GetServiceProvider() + { + IServiceProvider* provider{ nullptr }; + if (FAILED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_LOCAL_SERVER, __uuidof(provider), (PVOID*)&provider))) + { + return nullptr; + } + return provider; + } + + IVirtualDesktopManager* GetVirtualDesktopManager() + { + IVirtualDesktopManager* manager{ nullptr }; + IServiceProvider* serviceProvider = GetServiceProvider(); + if (serviceProvider == nullptr || FAILED(serviceProvider->QueryService(__uuidof(manager), &manager))) + { + return nullptr; + } + return manager; + } + + bool GetWindowDesktopId(HWND topLevelWindow, GUID* desktopId) + { + static IVirtualDesktopManager* virtualDesktopManager = GetVirtualDesktopManager(); + return (virtualDesktopManager != nullptr) && + SUCCEEDED(virtualDesktopManager->GetWindowDesktopId(topLevelWindow, desktopId)); + } + + bool GetZoneWindowDesktopId(IZoneWindow* zoneWindow, GUID* desktopId) + { + // Format: __ + std::wstring uniqueId = zoneWindow->UniqueId(); + std::wstring virtualDesktopId = uniqueId.substr(uniqueId.rfind('_') + 1); + if (virtualDesktopId == GUID_EmptyGUID) + { + return false; + } + return SUCCEEDED(CLSIDFromString(virtualDesktopId.c_str(), desktopId)); + } +} diff --git a/src/modules/fancyzones/lib/VirtualDesktopUtils.h b/src/modules/fancyzones/lib/VirtualDesktopUtils.h new file mode 100644 index 0000000000..c92d4b922c --- /dev/null +++ b/src/modules/fancyzones/lib/VirtualDesktopUtils.h @@ -0,0 +1,9 @@ +#pragma once + +#include "ZoneWindow.h" + +namespace VirtualDesktopUtils +{ + bool GetWindowDesktopId(HWND topLevelWindow, GUID* desktopId); + bool GetZoneWindowDesktopId(IZoneWindow* zoneWindow, GUID* desktopId); +} diff --git a/src/modules/fancyzones/lib/ZoneWindow.h b/src/modules/fancyzones/lib/ZoneWindow.h index e66c6f0b49..9e4f98f291 100644 --- a/src/modules/fancyzones/lib/ZoneWindow.h +++ b/src/modules/fancyzones/lib/ZoneWindow.h @@ -7,6 +7,7 @@ namespace ZoneWindowUtils const std::wstring& GetActiveZoneSetTmpPath(); const std::wstring& GetAppliedZoneSetTmpPath(); const std::wstring& GetCustomZoneSetsTmpPath(); + std::wstring GenerateUniqueId(HMONITOR monitor, PCWSTR deviceId, PCWSTR virtualDesktopId); }