[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; 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; 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 OnEditorExitEvent() noexcept;
void UpdateZoneSets() noexcept; void UpdateZoneSets() noexcept;
@@ -266,40 +267,33 @@ 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>, 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, {} }; if (monitor)
auto workAreaMap = m_workAreaHandler.GetWorkAreasByDesktopId(m_currentDesktopId);
if (workAreaMap.empty())
{ {
Logger::debug(L"No work area for the current desktop."); if (workAreaMap.contains(monitor))
} {
auto workArea = workAreaMap.at(monitor);
// Search application history on currently active monitor. return std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet>{ workArea, workArea->GetWindowZoneIndexes(window) };
if (workAreaMap.contains(monitor)) }
{ else
auto workArea = workAreaMap[monitor]; {
appZoneHistoryInfo = { workArea, workArea->GetWindowZoneIndexes(window) }; Logger::debug(L"No work area for the currently active monitor.");
}
} }
else 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) for (const auto& [monitor, workArea] : workAreaMap)
{ {
auto zoneIndexSet = workArea->GetWindowZoneIndexes(window); auto zoneIndexSet = workArea->GetWindowZoneIndexes(window);
if (!zoneIndexSet.empty()) 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 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 void FancyZones::WindowCreated(HWND window) noexcept
{ {
auto desktopId = m_virtualDesktop.GetWindowDesktopId(window); const bool moveToAppLastZone = m_settings->GetSettings()->appLastZone_moveWindows;
if (desktopId.has_value() && *desktopId != m_currentDesktopId) 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 // 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. // creation of new window. We need to check if window being processed is on currently active desktop.
return; 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 // Avoid processing splash screens, already stamped (zoned) windows, or those windows
// that belong to excluded applications list. // that belong to excluded applications list.
const bool isSplashScreen = FancyZonesUtils::IsSplashScreen(window); const bool isSplashScreen = FancyZonesUtils::IsSplashScreen(window);
const bool isZoned = reinterpret_cast<ZoneIndex>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID)) != 0; if (isSplashScreen)
const bool isCandidateForLastKnownZone = FancyZonesUtils::IsCandidateForLastKnownZone(window, m_settings->GetSettings()->excludedAppsArray);
const bool shouldProcessNewWindow = !isSplashScreen && !isZoned && isCandidateForLastKnownZone;
if ((moveToAppLastZone || openOnActiveMonitor) && shouldProcessNewWindow)
{ {
HMONITOR primary = MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY); return;
HMONITOR active = primary; }
POINT cursorPosition{}; const bool windowMinimized = IsIconic(window);
if (GetCursorPos(&cursorPosition)) if (windowMinimized)
{ {
active = MonitorFromPoint(cursorPosition, MONITOR_DEFAULTTOPRIMARY); return;
} }
bool windowZoned{ false }; const bool isZoned = reinterpret_cast<ZoneIndex>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID)) != 0;
if (moveToAppLastZone) if (isZoned)
{ {
const bool primaryActive = (primary == active); return;
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");
}
}
if (!windowZoned && openOnActiveMonitor) const bool isCandidateForLastKnownZone = FancyZonesUtils::IsCandidateForLastKnownZone(window, m_settings->GetSettings()->excludedAppsArray);
{ if (!isCandidateForLastKnownZone)
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] { MonitorUtils::OpenWindowOnActiveMonitor(window, active); } }).wait(); {
} 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()); 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 std::optional<GUID> VirtualDesktop::GetDesktopIdByTopLevelWindows() const
{ {
using result_t = std::vector<HWND>; using result_t = std::vector<HWND>;
@@ -222,16 +244,13 @@ std::optional<GUID> VirtualDesktop::GetDesktopIdByTopLevelWindows() const
}; };
EnumWindows(callback, reinterpret_cast<LPARAM>(&result)); EnumWindows(callback, reinterpret_cast<LPARAM>(&result));
GUID id;
BOOL isWindowOnCurrentDesktop = false;
for (const auto window : result) 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) // Otherwise keep checking other windows
{ return id;
return id;
}
} }
} }

View File

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