diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index ae60c17653..468cfb9b28 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -5,7 +5,6 @@ #include "FancyZones.h" #include "lib/Settings.h" #include "lib/ZoneWindow.h" -#include "lib/RegistryHelpers.h" #include "lib/JsonHelpers.h" #include "lib/ZoneSet.h" #include "trace.h" @@ -642,15 +641,25 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept // then this value will be empty. This means loading the first virtual desktop's configuration can be // funky the first time we load up at boot since the user will not have switched virtual desktops yet. GUID currentVirtualDesktopId{}; - if (SUCCEEDED(RegistryHelpers::GetCurrentVirtualDesktop(¤tVirtualDesktopId))) + if (VirtualDesktopUtils::GetCurrentVirtualDesktopId(¤tVirtualDesktopId)) { std::unique_lock writeLock(m_lock); m_currentVirtualDesktopId = currentVirtualDesktopId; } else { - // TODO: Use the previous "Desktop 1" fallback - // Need to maintain a map of desktop name to virtual desktop uuid + std::vector ids{}; + if (VirtualDesktopUtils::GetVirtualDekstopIds(m_virtualDesktopsRegKey, ids) && !ids.empty()) + { + std::unique_lock writeLock(m_lock); + m_currentVirtualDesktopId = ids[0]; + wil::unique_cotaskmem_string id; + if (changeType == DisplayChangeType::Initialization && + SUCCEEDED_LOG(StringFromCLSID(m_currentVirtualDesktopId, &id))) + { + JSONHelpers::FancyZonesDataInstance().UpdatePrimaryDesktopData(id.get()); + } + } } } @@ -1132,28 +1141,12 @@ void FancyZones::HandleVirtualDesktopUpdates(HANDLE fancyZonesDestroyedEvent) no // if fancyZonesDestroyedEvent is signalized or WaitForMultipleObjects failed, terminate thread execution return; } - DWORD bufferCapacity; - const WCHAR* key = L"VirtualDesktopIDs"; - // request regkey binary buffer capacity only - if (RegQueryValueExW(m_virtualDesktopsRegKey, key, 0, nullptr, nullptr, &bufferCapacity) != ERROR_SUCCESS) + std::vector ids{}; + if (VirtualDesktopUtils::GetVirtualDekstopIds(m_virtualDesktopsRegKey, ids)) { - return; + std::unordered_set idSet(std::begin(ids), std::end(ids)); + RegisterVirtualDesktopUpdates(idSet); } - std::unique_ptr buffer = std::make_unique(bufferCapacity); - // request regkey binary content - if (RegQueryValueExW(m_virtualDesktopsRegKey, key, 0, nullptr, buffer.get(), &bufferCapacity) != ERROR_SUCCESS) - { - return; - } - const size_t guidSize = sizeof(GUID); - std::unordered_set temp; - temp.reserve(bufferCapacity / guidSize); - for (size_t i = 0; i < bufferCapacity; i += guidSize) - { - GUID* guid = reinterpret_cast(buffer.get() + i); - temp.insert(*guid); - } - RegisterVirtualDesktopUpdates(temp); } } diff --git a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj index 9a8deaaef2..26a9bc454f 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj @@ -97,7 +97,6 @@ - diff --git a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters index af912e3803..8d758652f3 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters @@ -30,9 +30,6 @@ Header Files - - Header Files - Header Files diff --git a/src/modules/fancyzones/lib/JsonHelpers.cpp b/src/modules/fancyzones/lib/JsonHelpers.cpp index 5ff3abc28a..c86ac35e43 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.cpp +++ b/src/modules/fancyzones/lib/JsonHelpers.cpp @@ -1,6 +1,5 @@ #include "pch.h" #include "JsonHelpers.h" -#include "RegistryHelpers.h" #include "ZoneSet.h" #include "trace.h" @@ -37,6 +36,7 @@ namespace const wchar_t* FANCY_ZONES_DATA_FILE = L"zones-settings.json"; const wchar_t* DEFAULT_GUID = L"{00000000-0000-0000-0000-000000000000}"; + const wchar_t* REG_SETTINGS = L"Software\\SuperFancyZones"; std::wstring ExtractVirtualDesktopId(const std::wstring& deviceId) { @@ -321,6 +321,46 @@ namespace JSONHelpers } } + void FancyZonesData::UpdatePrimaryDesktopData(const std::wstring& desktopId) + { + // 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). + // This method will go through all our persisted data with default GUID and update it with + // valid one. + auto replaceDesktopId = [&desktopId](const std::wstring& deviceId) { + return deviceId.substr(0, deviceId.rfind('_') + 1) + desktopId; + }; + std::scoped_lock lock{ dataLock }; + for (auto& [path, data] : appZoneHistoryMap) + { + if (ExtractVirtualDesktopId(data.deviceId) == DEFAULT_GUID) + { + data.deviceId = replaceDesktopId(data.deviceId); + } + } + std::vector toReplace{}; + for (const auto& [id, data] : deviceInfoMap) + { + if (ExtractVirtualDesktopId(id) == DEFAULT_GUID) + { + toReplace.push_back(id); + } + } + for (const auto& id : toReplace) + { + auto mapEntry = deviceInfoMap.extract(id); + mapEntry.key() = replaceDesktopId(id); + deviceInfoMap.insert(std::move(mapEntry)); + } + if (activeDeviceId == DEFAULT_GUID) + { + activeDeviceId = replaceDesktopId(activeDeviceId); + } + SaveFancyZonesData(); + } + int FancyZonesData::GetAppLastZoneIndex(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const { std::scoped_lock lock{ dataLock }; @@ -640,7 +680,7 @@ namespace JSONHelpers { std::scoped_lock lock{ dataLock }; wchar_t key[256]; - StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", RegistryHelpers::REG_SETTINGS, L"Layouts"); + StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", REG_SETTINGS, L"Layouts"); HKEY hkey; if (RegOpenKeyExW(HKEY_CURRENT_USER, key, 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS) { diff --git a/src/modules/fancyzones/lib/JsonHelpers.h b/src/modules/fancyzones/lib/JsonHelpers.h index 3b5ecd27f0..ebdfbc352e 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.h +++ b/src/modules/fancyzones/lib/JsonHelpers.h @@ -233,6 +233,7 @@ namespace JSONHelpers void AddDevice(const std::wstring& deviceId); bool RemoveDevicesByVirtualDesktopId(const std::wstring& virtualDesktopId); void CloneDeviceInfo(const std::wstring& source, const std::wstring& destination); + void UpdatePrimaryDesktopData(const std::wstring& desktopId); int GetAppLastZoneIndex(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const; bool RemoveAppLastZone(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId); diff --git a/src/modules/fancyzones/lib/RegistryHelpers.h b/src/modules/fancyzones/lib/RegistryHelpers.h deleted file mode 100644 index e16213e4a6..0000000000 --- a/src/modules/fancyzones/lib/RegistryHelpers.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -namespace RegistryHelpers -{ - static PCWSTR REG_SETTINGS = L"Software\\SuperFancyZones"; - static PCWSTR APP_ZONE_HISTORY_SUBKEY = L"AppZoneHistory"; - - inline HRESULT GetCurrentVirtualDesktop(_Out_ GUID* id) - { - *id = GUID_NULL; - - DWORD sessionId; - ProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - - wchar_t sessionKeyPath[256]{}; - RETURN_IF_FAILED( - StringCchPrintfW( - sessionKeyPath, - ARRAYSIZE(sessionKeyPath), - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SessionInfo\\%d\\VirtualDesktops", - sessionId)); - wil::unique_hkey key{}; - GUID value{}; - - if (RegOpenKeyExW(HKEY_CURRENT_USER, sessionKeyPath, 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) - { - DWORD size = sizeof(value); - if (RegQueryValueExW(key.get(), L"CurrentVirtualDesktop", 0, nullptr, reinterpret_cast(&value), &size) == ERROR_SUCCESS) - { - *id = value; - return S_OK; - } - } - return E_FAIL; - } -} \ No newline at end of file diff --git a/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp b/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp index 1a8e892854..597541071a 100644 --- a/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp +++ b/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp @@ -7,6 +7,9 @@ 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}"; + const wchar_t RegCurrentVirtualDesktop[] = L"CurrentVirtualDesktop"; + const wchar_t RegVirtualDesktopIds[] = L"VirtualDesktopIDs"; + IServiceProvider* GetServiceProvider() { IServiceProvider* provider{ nullptr }; @@ -46,4 +49,57 @@ namespace VirtualDesktopUtils } return SUCCEEDED(CLSIDFromString(virtualDesktopId.c_str(), desktopId)); } + + bool GetCurrentVirtualDesktopId(GUID* desktopId) + { + DWORD sessionId; + ProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + + wchar_t sessionKeyPath[256]{}; + RETURN_IF_FAILED( + StringCchPrintfW( + sessionKeyPath, + ARRAYSIZE(sessionKeyPath), + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SessionInfo\\%d\\VirtualDesktops", + sessionId)); + + wil::unique_hkey key{}; + GUID value{}; + if (RegOpenKeyExW(HKEY_CURRENT_USER, sessionKeyPath, 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) + { + DWORD size = sizeof(GUID); + if (RegQueryValueExW(key.get(), RegCurrentVirtualDesktop, 0, nullptr, reinterpret_cast(&value), &size) == ERROR_SUCCESS) + { + *desktopId = value; + return true; + } + } + return false; + } + + bool GetVirtualDekstopIds(HKEY hKey, std::vector& ids) + { + DWORD bufferCapacity; + // request regkey binary buffer capacity only + if (RegQueryValueExW(hKey, RegVirtualDesktopIds, 0, nullptr, nullptr, &bufferCapacity) != ERROR_SUCCESS) + { + return false; + } + std::unique_ptr buffer = std::make_unique(bufferCapacity); + // request regkey binary content + if (RegQueryValueExW(hKey, RegVirtualDesktopIds, 0, nullptr, buffer.get(), &bufferCapacity) != ERROR_SUCCESS) + { + return false; + } + const size_t guidSize = sizeof(GUID); + std::vector temp; + temp.reserve(bufferCapacity / guidSize); + for (size_t i = 0; i < bufferCapacity; i += guidSize) + { + GUID* guid = reinterpret_cast(buffer.get() + i); + temp.push_back(*guid); + } + ids = std::move(temp); + return true; + } } diff --git a/src/modules/fancyzones/lib/VirtualDesktopUtils.h b/src/modules/fancyzones/lib/VirtualDesktopUtils.h index c92d4b922c..ff40adb2f1 100644 --- a/src/modules/fancyzones/lib/VirtualDesktopUtils.h +++ b/src/modules/fancyzones/lib/VirtualDesktopUtils.h @@ -6,4 +6,6 @@ namespace VirtualDesktopUtils { bool GetWindowDesktopId(HWND topLevelWindow, GUID* desktopId); bool GetZoneWindowDesktopId(IZoneWindow* zoneWindow, GUID* desktopId); + bool GetCurrentVirtualDesktopId(GUID* desktopId); + bool GetVirtualDekstopIds(HKEY hKey, std::vector& ids); } diff --git a/src/modules/fancyzones/lib/ZoneSet.cpp b/src/modules/fancyzones/lib/ZoneSet.cpp index 269632727b..15c0d8a4fc 100644 --- a/src/modules/fancyzones/lib/ZoneSet.cpp +++ b/src/modules/fancyzones/lib/ZoneSet.cpp @@ -2,7 +2,6 @@ #include "util.h" #include "lib/ZoneSet.h" -#include "lib/RegistryHelpers.h" #include diff --git a/src/modules/fancyzones/lib/ZoneWindow.cpp b/src/modules/fancyzones/lib/ZoneWindow.cpp index 684995f0cc..4f2c5d4ac4 100644 --- a/src/modules/fancyzones/lib/ZoneWindow.cpp +++ b/src/modules/fancyzones/lib/ZoneWindow.cpp @@ -5,7 +5,6 @@ #include "ZoneWindow.h" #include "trace.h" #include "util.h" -#include "RegistryHelpers.h" #include #include