[Fancy Zones] Restore Console Applications (#12905)

This commit is contained in:
Seraphima Zykova
2021-08-26 20:47:27 +03:00
committed by GitHub
parent 078cf2c22f
commit e35568f63d
3 changed files with 132 additions and 70 deletions

View File

@@ -157,8 +157,9 @@ private:
void OnSettingsChanged() noexcept;
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept;
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept;
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> zoneWindow, const ZoneIndexSet& zoneIndexSet) noexcept;
bool MoveToAppLastZone(HWND window, HMONITOR active, HMONITOR primary) noexcept;
void OnEditorExitEvent() noexcept;
void UpdateZoneSets() noexcept;
@@ -266,40 +267,33 @@ FancyZones::VirtualDesktopChanged() noexcept
PostMessage(m_window, WM_PRIV_VD_SWITCH, 0, 0);
}
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> FancyZones::GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> FancyZones::GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept
{
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> appZoneHistoryInfo{ nullptr, {} };
auto workAreaMap = m_workAreaHandler.GetWorkAreasByDesktopId(m_currentDesktopId);
if (workAreaMap.empty())
if (monitor)
{
Logger::debug(L"No work area for the current desktop.");
}
// Search application history on currently active monitor.
if (workAreaMap.contains(monitor))
{
auto workArea = workAreaMap[monitor];
appZoneHistoryInfo = { workArea, workArea->GetWindowZoneIndexes(window) };
if (workAreaMap.contains(monitor))
{
auto workArea = workAreaMap.at(monitor);
return std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet>{ workArea, workArea->GetWindowZoneIndexes(window) };
}
else
{
Logger::debug(L"No work area for the currently active monitor.");
}
}
else
{
Logger::debug(L"No work area for the currently active monitor.");
}
if (isPrimaryMonitor && appZoneHistoryInfo.second.empty())
{
// No application history on primary monitor, search on remaining monitors.
for (const auto& [monitor, workArea] : workAreaMap)
{
auto zoneIndexSet = workArea->GetWindowZoneIndexes(window);
if (!zoneIndexSet.empty())
{
return { workArea, zoneIndexSet };
return std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet>{ workArea, zoneIndexSet };
}
}
}
return appZoneHistoryInfo;
return std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet>{ nullptr, {} };
}
void FancyZones::MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> zoneWindow, const ZoneIndexSet& zoneIndexSet) noexcept
@@ -313,62 +307,108 @@ void FancyZones::MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> zoneW
}
}
bool FancyZones::MoveToAppLastZone(HWND window, HMONITOR active, HMONITOR primary) noexcept
{
auto workAreaMap = m_workAreaHandler.GetWorkAreasByDesktopId(m_currentDesktopId);
if (workAreaMap.empty())
{
Logger::trace(L"No work area for the current desktop.");
return false;
}
// Search application history on currently active monitor.
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> appZoneHistoryInfo = GetAppZoneHistoryInfo(window, active, workAreaMap);
// No application history on currently active monitor
if (appZoneHistoryInfo.second.empty())
{
// Search application history on primary monitor.
appZoneHistoryInfo = GetAppZoneHistoryInfo(window, primary, workAreaMap);
}
// No application history on currently active and primary monitors
if (appZoneHistoryInfo.second.empty())
{
// Search application history on remaining monitors.
appZoneHistoryInfo = GetAppZoneHistoryInfo(window, nullptr, workAreaMap);
}
if (!appZoneHistoryInfo.second.empty())
{
MoveWindowIntoZone(window, appZoneHistoryInfo.first, appZoneHistoryInfo.second);
return true;
}
else
{
Logger::trace(L"App zone history is empty for the processing window on a current virtual desktop");
}
return false;
}
void FancyZones::WindowCreated(HWND window) noexcept
{
auto desktopId = m_virtualDesktop.GetWindowDesktopId(window);
if (desktopId.has_value() && *desktopId != m_currentDesktopId)
const bool moveToAppLastZone = m_settings->GetSettings()->appLastZone_moveWindows;
const bool openOnActiveMonitor = m_settings->GetSettings()->openWindowOnActiveMonitor;
if (!moveToAppLastZone && !openOnActiveMonitor)
{
// Nothing to do here then.
return;
}
if (!m_virtualDesktop.IsWindowOnCurrentDesktop(window))
{
// Switch between virtual desktops results with posting same windows messages that also indicate
// creation of new window. We need to check if window being processed is on currently active desktop.
return;
}
const bool moveToAppLastZone = m_settings->GetSettings()->appLastZone_moveWindows;
const bool openOnActiveMonitor = m_settings->GetSettings()->openWindowOnActiveMonitor;
// Avoid processing splash screens, already stamped (zoned) windows, or those windows
// that belong to excluded applications list.
const bool isSplashScreen = FancyZonesUtils::IsSplashScreen(window);
const bool isZoned = reinterpret_cast<ZoneIndex>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID)) != 0;
const bool isCandidateForLastKnownZone = FancyZonesUtils::IsCandidateForLastKnownZone(window, m_settings->GetSettings()->excludedAppsArray);
const bool shouldProcessNewWindow = !isSplashScreen && !isZoned && isCandidateForLastKnownZone;
if ((moveToAppLastZone || openOnActiveMonitor) && shouldProcessNewWindow)
if (isSplashScreen)
{
HMONITOR primary = MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY);
HMONITOR active = primary;
return;
}
POINT cursorPosition{};
if (GetCursorPos(&cursorPosition))
{
active = MonitorFromPoint(cursorPosition, MONITOR_DEFAULTTOPRIMARY);
}
const bool windowMinimized = IsIconic(window);
if (windowMinimized)
{
return;
}
bool windowZoned{ false };
if (moveToAppLastZone)
{
const bool primaryActive = (primary == active);
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> appZoneHistoryInfo = GetAppZoneHistoryInfo(window, active, primaryActive);
if (!appZoneHistoryInfo.second.empty())
{
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");
}
}
const bool isZoned = reinterpret_cast<ZoneIndex>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID)) != 0;
if (isZoned)
{
return;
}
if (!windowZoned && openOnActiveMonitor)
{
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] { MonitorUtils::OpenWindowOnActiveMonitor(window, active); } }).wait();
}
const bool isCandidateForLastKnownZone = FancyZonesUtils::IsCandidateForLastKnownZone(window, m_settings->GetSettings()->excludedAppsArray);
if (!isCandidateForLastKnownZone)
{
return;
}
HMONITOR primary = MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY);
HMONITOR active = primary;
POINT cursorPosition{};
if (GetCursorPos(&cursorPosition))
{
active = MonitorFromPoint(cursorPosition, MONITOR_DEFAULTTOPRIMARY);
}
bool movedToAppLastZone = false;
if (moveToAppLastZone)
{
movedToAppLastZone = MoveToAppLastZone(window, active, primary);
}
// Open on active monitor if window wasn't zoned
if (openOnActiveMonitor && !movedToAppLastZone)
{
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] { MonitorUtils::OpenWindowOnActiveMonitor(window, active); } }).wait();
}
}

View File

@@ -210,6 +210,28 @@ std::optional<std::vector<GUID>> VirtualDesktop::GetVirtualDesktopIds() const
return GetVirtualDesktopIds(GetVirtualDesktopsRegKey());
}
bool VirtualDesktop::IsWindowOnCurrentDesktop(HWND window) const
{
std::optional<GUID> id = GetDesktopId(window);
return id.has_value();
}
std::optional<GUID> VirtualDesktop::GetDesktopId(HWND window) const
{
GUID id;
BOOL isWindowOnCurrentDesktop = false;
if (m_vdManager->IsWindowOnCurrentVirtualDesktop(window, &isWindowOnCurrentDesktop) == S_OK && isWindowOnCurrentDesktop)
{
// Filter windows such as Windows Start Menu, Task Switcher, etc.
if (m_vdManager->GetWindowDesktopId(window, &id) == S_OK && id != GUID_NULL)
{
return id;
}
}
return std::nullopt;
}
std::optional<GUID> VirtualDesktop::GetDesktopIdByTopLevelWindows() const
{
using result_t = std::vector<HWND>;
@@ -222,16 +244,13 @@ std::optional<GUID> VirtualDesktop::GetDesktopIdByTopLevelWindows() const
};
EnumWindows(callback, reinterpret_cast<LPARAM>(&result));
GUID id;
BOOL isWindowOnCurrentDesktop = false;
for (const auto window : result)
{
if (m_vdManager->IsWindowOnCurrentVirtualDesktop(window, &isWindowOnCurrentDesktop) == ERROR_SUCCESS && isWindowOnCurrentDesktop)
std::optional<GUID> id = GetDesktopId(window);
if (id.has_value())
{
if (m_vdManager->GetWindowDesktopId(window, &id) == ERROR_SUCCESS && id != GUID_NULL)
{
return id;
}
// Otherwise keep checking other windows
return id;
}
}

View File

@@ -16,6 +16,9 @@ public:
std::optional<GUID> GetCurrentVirtualDesktopId() const;
std::optional<std::vector<GUID>> GetVirtualDesktopIds() const;
bool IsWindowOnCurrentDesktop(HWND window) const;
std::optional<GUID> GetDesktopId(HWND window) const;
private:
std::function<void()> m_vdInitCallback;
std::function<void()> m_vdUpdatedCallback;