Skip to content

Commit

Permalink
[FancyZones] Window opening on the last zone (#12284)
Browse files Browse the repository at this point in the history
  • Loading branch information
SeraphimaZykova committed Jul 9, 2021
1 parent d85c3f8 commit 9d597fa
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 39 deletions.
51 changes: 32 additions & 19 deletions src/common/utils/process_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <shlwapi.h>

#include <string>
#include <thread>

// Get the executable path or module name for modern apps
inline std::wstring get_process_path(DWORD pid) noexcept
Expand All @@ -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<DWORD*>(param);
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
if (pid != *new_pid_ptr)
{
*new_pid_ptr = pid;
return FALSE;
}
else
{
return TRUE;
}
},
reinterpret_cast<LPARAM>(&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<DWORD*>(param);
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
if (pid != *new_pid_ptr)
{
*new_pid_ptr = pid;
return FALSE;
}
else
{
return TRUE;
}
},
reinterpret_cast<LPARAM>(&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;
}

Expand Down
46 changes: 26 additions & 20 deletions src/modules/fancyzones/FancyZonesLib/FancyZones.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ struct FancyZones : public winrt::implements<FancyZones, IFancyZones, IFancyZone

void OnSettingsChanged() noexcept;

std::pair<winrt::com_ptr<IWorkArea>, std::vector<size_t>> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept;
std::pair<winrt::com_ptr<IWorkArea>, std::vector<size_t>> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept;
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> zoneWindow, const std::vector<size_t>& zoneIndexSet) noexcept;

Expand Down Expand Up @@ -266,27 +265,25 @@ FancyZones::VirtualDesktopChanged() noexcept
PostMessage(m_window, WM_PRIV_VD_SWITCH, 0, 0);
}

std::pair<winrt::com_ptr<IWorkArea>, std::vector<size_t>> FancyZones::GetAppZoneHistoryInfo(
HWND window,
HMONITOR monitor,
std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& 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<winrt::com_ptr<IWorkArea>, std::vector<size_t>> FancyZones::GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept
{
std::pair<winrt::com_ptr<IWorkArea>, std::vector<size_t>> 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())
{
Expand Down Expand Up @@ -351,13 +348,22 @@ void FancyZones::WindowCreated(HWND window) noexcept
{
const bool primaryActive = (primary == active);
std::pair<winrt::com_ptr<IWorkArea>, std::vector<size_t>> 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();
Expand Down

0 comments on commit 9d597fa

Please sign in to comment.