mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-11 20:23:07 +08:00
[FancyZones] Window opening on the last zone (#12284)
This commit is contained in:
parent
d85c3f8cc9
commit
9d597faabc
@ -4,6 +4,7 @@
|
|||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
// Get the executable path or module name for modern apps
|
// Get the executable path or module name for modern apps
|
||||||
inline std::wstring get_process_path(DWORD pid) noexcept
|
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
|
inline std::wstring get_process_path(HWND window) noexcept
|
||||||
{
|
{
|
||||||
const static std::wstring app_frame_host = L"ApplicationFrameHost.exe";
|
const static std::wstring app_frame_host = L"ApplicationFrameHost.exe";
|
||||||
|
|
||||||
DWORD pid{};
|
DWORD pid{};
|
||||||
GetWindowThreadProcessId(window, &pid);
|
GetWindowThreadProcessId(window, &pid);
|
||||||
auto name = get_process_path(pid);
|
auto name = get_process_path(pid);
|
||||||
|
|
||||||
if (name.length() >= app_frame_host.length() &&
|
if (name.length() >= app_frame_host.length() &&
|
||||||
name.compare(name.length() - app_frame_host.length(), app_frame_host.length(), app_frame_host) == 0)
|
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
|
// It is a UWP app. We will enumerate the windows and look for one created
|
||||||
// by something with a different PID
|
// 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;
|
DWORD new_pid = pid;
|
||||||
EnumChildWindows(
|
|
||||||
window, [](HWND hwnd, LPARAM param) -> BOOL {
|
const int retryAttempts = 10;
|
||||||
auto new_pid_ptr = reinterpret_cast<DWORD*>(param);
|
for (int retry = 0; retry < retryAttempts && pid == new_pid; retry++)
|
||||||
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);
|
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;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,6 @@ private:
|
|||||||
|
|
||||||
void OnSettingsChanged() noexcept;
|
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;
|
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;
|
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> zoneWindow, const std::vector<size_t>& zoneIndexSet) noexcept;
|
||||||
|
|
||||||
@ -266,27 +265,25 @@ FancyZones::VirtualDesktopChanged() noexcept
|
|||||||
PostMessage(m_window, WM_PRIV_VD_SWITCH, 0, 0);
|
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>> FancyZones::GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept
|
||||||
{
|
{
|
||||||
std::pair<winrt::com_ptr<IWorkArea>, std::vector<size_t>> appZoneHistoryInfo{ nullptr, {} };
|
std::pair<winrt::com_ptr<IWorkArea>, std::vector<size_t>> appZoneHistoryInfo{ nullptr, {} };
|
||||||
auto workAreaMap = m_workAreaHandler.GetWorkAreasByDesktopId(m_currentDesktopId);
|
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.
|
// 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())
|
if (isPrimaryMonitor && appZoneHistoryInfo.second.empty())
|
||||||
{
|
{
|
||||||
@ -351,13 +348,22 @@ void FancyZones::WindowCreated(HWND window) noexcept
|
|||||||
{
|
{
|
||||||
const bool primaryActive = (primary == active);
|
const bool primaryActive = (primary == active);
|
||||||
std::pair<winrt::com_ptr<IWorkArea>, std::vector<size_t>> appZoneHistoryInfo = GetAppZoneHistoryInfo(window, active, primaryActive);
|
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);
|
const bool windowMinimized = IsIconic(window);
|
||||||
windowZoned = true;
|
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)
|
if (!windowZoned && openOnActiveMonitor)
|
||||||
{
|
{
|
||||||
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] { MonitorUtils::OpenWindowOnActiveMonitor(window, active); } }).wait();
|
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] { MonitorUtils::OpenWindowOnActiveMonitor(window, active); } }).wait();
|
||||||
|
Loading…
Reference in New Issue
Block a user