From 9d597faabc43f9838730f54e28dcc83aad48bd92 Mon Sep 17 00:00:00 2001 From: Seraphima Zykova Date: Fri, 9 Jul 2021 20:18:21 +0300 Subject: [PATCH] [FancyZones] Window opening on the last zone (#12284) --- src/common/utils/process_path.h | 51 ++++++++++++------- .../fancyzones/FancyZonesLib/FancyZones.cpp | 46 +++++++++-------- 2 files changed, 58 insertions(+), 39 deletions(-) diff --git a/src/common/utils/process_path.h b/src/common/utils/process_path.h index 4f35b20987..e04f4739a4 100644 --- a/src/common/utils/process_path.h +++ b/src/common/utils/process_path.h @@ -4,6 +4,7 @@ #include #include +#include // Get the executable path or module name for modern apps inline std::wstring get_process_path(DWORD pid) noexcept @@ -28,37 +29,49 @@ inline std::wstring get_process_path(DWORD pid) noexcept inline std::wstring get_process_path(HWND window) noexcept { const static std::wstring app_frame_host = L"ApplicationFrameHost.exe"; + DWORD pid{}; GetWindowThreadProcessId(window, &pid); auto name = get_process_path(pid); + if (name.length() >= app_frame_host.length() && name.compare(name.length() - app_frame_host.length(), app_frame_host.length(), app_frame_host) == 0) { // It is a UWP app. We will enumerate the windows and look for one created // by something with a different PID + // It might take a time to connect the process. That's the reason for the retry loop here DWORD new_pid = pid; - EnumChildWindows( - window, [](HWND hwnd, LPARAM param) -> BOOL { - auto new_pid_ptr = reinterpret_cast(param); - DWORD pid; - GetWindowThreadProcessId(hwnd, &pid); - if (pid != *new_pid_ptr) - { - *new_pid_ptr = pid; - return FALSE; - } - else - { - return TRUE; - } - }, - reinterpret_cast(&new_pid)); - // If we have a new pid, get the new name. - if (new_pid != pid) + + const int retryAttempts = 10; + for (int retry = 0; retry < retryAttempts && pid == new_pid; retry++) { - return get_process_path(new_pid); + EnumChildWindows( + window, [](HWND hwnd, LPARAM param) -> BOOL { + auto new_pid_ptr = reinterpret_cast(param); + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + if (pid != *new_pid_ptr) + { + *new_pid_ptr = pid; + return FALSE; + } + else + { + return TRUE; + } + }, + reinterpret_cast(&new_pid)); + + // If we have a new pid, get the new name. + if (new_pid != pid) + { + return get_process_path(new_pid); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } + return name; } diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp b/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp index 020852625c..ae1a05b4f4 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp +++ b/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp @@ -156,7 +156,6 @@ private: void OnSettingsChanged() noexcept; - std::pair, std::vector> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, std::unordered_map>& workAreaMap) noexcept; std::pair, std::vector> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept; void MoveWindowIntoZone(HWND window, winrt::com_ptr zoneWindow, const std::vector& zoneIndexSet) noexcept; @@ -266,27 +265,25 @@ FancyZones::VirtualDesktopChanged() noexcept PostMessage(m_window, WM_PRIV_VD_SWITCH, 0, 0); } -std::pair, std::vector> FancyZones::GetAppZoneHistoryInfo( - HWND window, - HMONITOR monitor, - std::unordered_map>& workAreaMap) noexcept -{ - if (workAreaMap.contains(monitor)) - { - auto workArea = workAreaMap[monitor]; - workAreaMap.erase(monitor); // monitor processed, remove entry from the map - return { workArea, workArea->GetWindowZoneIndexes(window) }; - } - return { nullptr, {} }; -} - std::pair, std::vector> FancyZones::GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept { std::pair, std::vector> appZoneHistoryInfo{ nullptr, {} }; auto workAreaMap = m_workAreaHandler.GetWorkAreasByDesktopId(m_currentDesktopId); + if (workAreaMap.empty()) + { + Logger::debug(L"No work area for the current desktop."); + } // Search application history on currently active monitor. - appZoneHistoryInfo = GetAppZoneHistoryInfo(window, monitor, workAreaMap); + if (workAreaMap.contains(monitor)) + { + auto workArea = workAreaMap[monitor]; + appZoneHistoryInfo = { workArea, workArea->GetWindowZoneIndexes(window) }; + } + else + { + Logger::debug(L"No work area for the currently active monitor."); + } if (isPrimaryMonitor && appZoneHistoryInfo.second.empty()) { @@ -351,13 +348,22 @@ void FancyZones::WindowCreated(HWND window) noexcept { const bool primaryActive = (primary == active); std::pair, std::vector> appZoneHistoryInfo = GetAppZoneHistoryInfo(window, active, primaryActive); - const bool windowMinimized = IsIconic(window); - if (!appZoneHistoryInfo.second.empty() && !windowMinimized) + + if (!appZoneHistoryInfo.second.empty()) { - MoveWindowIntoZone(window, appZoneHistoryInfo.first, appZoneHistoryInfo.second); - windowZoned = true; + const bool windowMinimized = IsIconic(window); + if (!windowMinimized) + { + MoveWindowIntoZone(window, appZoneHistoryInfo.first, appZoneHistoryInfo.second); + windowZoned = true; + } + } + else + { + Logger::warn(L"App zone history is empty for the processing window on a current virtual desktop"); } } + if (!windowZoned && openOnActiveMonitor) { m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] { MonitorUtils::OpenWindowOnActiveMonitor(window, active); } }).wait();