Make FancyZone distinguish different modern apps.

This commit is contained in:
Bartosz Sosnowski
2019-09-19 15:33:28 +02:00
committed by Bartosz Sosnowski
parent 5d75feebdc
commit 0b86941a3b
3 changed files with 54 additions and 24 deletions

View File

@@ -168,12 +168,11 @@ IFACEMETHODIMP_(void) FancyZones::WindowCreated(HWND window) noexcept
{ {
if (m_settings->GetSettings().appLastZone_moveWindows) if (m_settings->GetSettings().appLastZone_moveWindows)
{ {
wchar_t processPath[MAX_PATH] = { 0 }; auto processPath = GetProcessPath(window);
DWORD modulePathSize = GetProcessPath(window, processPath, static_cast<DWORD>(MAX_PATH)); if (!processPath.empty())
if (modulePathSize > 0)
{ {
INT zoneIndex = -1; INT zoneIndex = -1;
LRESULT res = RegistryHelpers::GetAppLastZone(window, processPath, &zoneIndex); LRESULT res = RegistryHelpers::GetAppLastZone(window, processPath.data(), &zoneIndex);
if ((res == ERROR_SUCCESS) && (zoneIndex != -1)) if ((res == ERROR_SUCCESS) && (zoneIndex != -1))
{ {
MoveWindowIntoZoneByIndex(window, zoneIndex); MoveWindowIntoZoneByIndex(window, zoneIndex);
@@ -670,11 +669,10 @@ void FancyZones::MoveSizeEndInternal(HWND window, POINT const& ptScreen, require
{ {
::RemoveProp(window, ZONE_STAMP); ::RemoveProp(window, ZONE_STAMP);
wchar_t processPath[MAX_PATH]{}; auto processPath = GetProcessPath(window);
DWORD processPathSize = GetProcessPath(window, processPath, static_cast<DWORD>(MAX_PATH)); if (!processPath.empty())
if (processPathSize > 0)
{ {
RegistryHelpers::SaveAppLastZone(window, processPath, -1); RegistryHelpers::SaveAppLastZone(window, processPath.data(), -1);
} }
} }
} }

View File

@@ -1252,14 +1252,13 @@ int ZoneWindow::GetSwitchButtonIndexFromPoint(POINT ptClient) noexcept
IFACEMETHODIMP_(void) ZoneWindow::SaveWindowProcessToZoneIndex(HWND window) noexcept IFACEMETHODIMP_(void) ZoneWindow::SaveWindowProcessToZoneIndex(HWND window) noexcept
{ {
wchar_t processPath[MAX_PATH] = { 0 }; auto processPath = GetProcessPath(window);
DWORD processPathSize = GetProcessPath(window, processPath, static_cast<DWORD>(MAX_PATH)); if (!processPath.empty())
if (processPathSize > 0)
{ {
DWORD zoneIndex = static_cast<DWORD>(m_activeZoneSet->GetZoneIndexFromWindow(window)); DWORD zoneIndex = static_cast<DWORD>(m_activeZoneSet->GetZoneIndexFromWindow(window));
if (zoneIndex != -1) if (zoneIndex != -1)
{ {
RegistryHelpers::SaveAppLastZone(window, processPath, zoneIndex); RegistryHelpers::SaveAppLastZone(window, processPath.data(), zoneIndex);
} }
} }
} }

View File

@@ -134,19 +134,52 @@ inline void ParseDeviceId(PCWSTR deviceId, PWSTR parsedId, size_t size)
} }
} }
inline DWORD GetProcessPath(HWND window, LPWSTR processPath, DWORD processPathMaxSize) noexcept inline std::wstring GetProcessPathByPID(DWORD pid)
{ {
wil::unique_handle process(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid));
std::wstring name;
if (process && process.get() != INVALID_HANDLE_VALUE)
{
name.resize(MAX_PATH);
DWORD name_length = static_cast<DWORD>(name.length());
QueryFullProcessImageNameW(process.get(), 0, (LPWSTR)name.data(), &name_length);
name.resize(name_length);
}
return name;
}
inline std::wstring GetProcessPath(HWND window) noexcept
{
const static std::wstring app_frame_host = L"ApplicationFrameHost.exe";
DWORD pid{}; DWORD pid{};
GetWindowThreadProcessId(window, &pid); GetWindowThreadProcessId(window, &pid);
auto name = GetProcessPathByPID(pid);
DWORD numCopiedChars = 0; if (name.length() >= app_frame_host.length() &&
wil::unique_handle windowProcessHandle(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid)); name.compare(name.length() - app_frame_host.length(), app_frame_host.length(), app_frame_host) == 0)
if (windowProcessHandle && (windowProcessHandle.get() != INVALID_HANDLE_VALUE))
{ {
// numCopiedChars first holds the size of processPath[], will then hold amount of characters returned by QueryFullProcessImageNameW // It is a UWP app. We will enumarate the windows and look for one created
// if QueryFullProcessImageNameW fails, numCopiedChars will be zero. // by something with a different PID
numCopiedChars = processPathMaxSize; DWORD new_pid = pid;
QueryFullProcessImageNameW(windowProcessHandle.get(), 0, processPath, &numCopiedChars); 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;
} }
return numCopiedChars; else
{
return TRUE;
}
}, reinterpret_cast<LPARAM>(&new_pid));
// If we have a new pid, get the new name.
if (new_pid != pid)
{
return GetProcessPathByPID(new_pid);
}
}
return name;
} }