diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index a3cbdca23f..d66bb663a7 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -211,9 +211,14 @@ private: void RegisterVirtualDesktopUpdates(std::vector& ids) noexcept; bool IsSplashScreen(HWND window); + bool ShouldProcessNewWindow(HWND window) noexcept; + std::vector GetZoneIndexSetFromWorkAreaHistory(HWND window, winrt::com_ptr workArea) noexcept; + std::pair, std::vector> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, std::unordered_map>& workAreaMap) noexcept; + std::pair, std::vector> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept; + void MoveWindowIntoZone(HWND window, winrt::com_ptr zoneWindow, const std::vector& zoneIndexSet) noexcept; void OnEditorExitEvent() noexcept; - bool ProcessSnapHotkey() noexcept; + bool ShouldProcessSnapHotkey() noexcept; std::vector> GetRawMonitorData() noexcept; std::vector GetMonitorsSorted() noexcept; @@ -323,35 +328,103 @@ FancyZones::VirtualDesktopInitialize() noexcept PostMessage(m_window, WM_PRIV_VD_INIT, 0, 0); } +bool FancyZones::ShouldProcessNewWindow(HWND window) noexcept +{ + // Avoid processing splash screens, already stamped (zoned) windows, or those windows + // that belong to excluded applications list. + if (IsSplashScreen(window) || + (reinterpret_cast(::GetProp(window, MULTI_ZONE_STAMP)) != 0) || + !IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray)) + { + return false; + } + return true; +} + +std::vector FancyZones::GetZoneIndexSetFromWorkAreaHistory( + HWND window, winrt::com_ptr workArea) noexcept +{ + const auto activeZoneSet = workArea->ActiveZoneSet(); + if (activeZoneSet) + { + wil::unique_cotaskmem_string zoneSetId; + if (SUCCEEDED(StringFromCLSID(activeZoneSet->Id(), &zoneSetId))) + { + return JSONHelpers::FancyZonesDataInstance().GetAppLastZoneIndexSet(window, workArea->UniqueId(), zoneSetId.get()); + } + } + return {}; +} + +std::pair, std::vector> FancyZones::GetAppZoneHistoryInfo( + HWND window, + HMONITOR monitor, + std::unordered_map>& workAreaMap) noexcept +{ + if (workAreaMap.contains(monitor)) + { + auto workArea = workAreaMap[monitor]; + workAreaMap.erase(monitor); // monitor processed, remove entry from the map + return { workArea, GetZoneIndexSetFromWorkAreaHistory(window, workArea) }; + } + return { nullptr, {} }; +} + +std::pair, std::vector> FancyZones::GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept +{ + std::pair, std::vector> appZoneHistoryInfo{ nullptr, {} }; + auto workAreaMap = m_workAreaHandler.GetWorkAreasByDesktopId(m_currentDesktopId); + + // Search application history on currently active monitor. + appZoneHistoryInfo = GetAppZoneHistoryInfo(window, monitor, workAreaMap); + + if (isPrimaryMonitor && appZoneHistoryInfo.second.empty()) + { + // No application history on primary monitor, search on remaining monitors. + for (const auto& [monitor, workArea] : workAreaMap) + { + auto zoneIndexSet = GetZoneIndexSetFromWorkAreaHistory(window, workArea); + if (!zoneIndexSet.empty()) + { + return { workArea, zoneIndexSet }; + } + } + } + + return appZoneHistoryInfo; +} + +void FancyZones::MoveWindowIntoZone(HWND window, winrt::com_ptr zoneWindow, const std::vector& zoneIndexSet) noexcept +{ + auto& fancyZonesData = JSONHelpers::FancyZonesDataInstance(); + if (!fancyZonesData.IsAnotherWindowOfApplicationInstanceZoned(window, zoneWindow->UniqueId())) + { + m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, zoneWindow); + fancyZonesData.UpdateProcessIdToHandleMap(window, zoneWindow->UniqueId()); + } +} + // IFancyZonesCallback IFACEMETHODIMP_(void) FancyZones::WindowCreated(HWND window) noexcept { std::shared_lock readLock(m_lock); - - if (m_settings->GetSettings()->appLastZone_moveWindows && IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray)) + if (m_settings->GetSettings()->appLastZone_moveWindows && ShouldProcessNewWindow(window)) { - auto zoneWindow = m_workAreaHandler.GetWorkArea(window); - if (zoneWindow) - { - const auto activeZoneSet = zoneWindow->ActiveZoneSet(); - if (activeZoneSet) - { - auto& fancyZonesData = JSONHelpers::FancyZonesDataInstance(); + HMONITOR primary = MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY); + HMONITOR active = primary; - wil::unique_cotaskmem_string guidString; - if (SUCCEEDED(StringFromCLSID(activeZoneSet->Id(), &guidString))) - { - std::vector zoneIndexSet = fancyZonesData.GetAppLastZoneIndexSet(window, zoneWindow->UniqueId(), guidString.get()); - if (zoneIndexSet.size() && - !IsSplashScreen(window) && - !fancyZonesData.IsAnotherWindowOfApplicationInstanceZoned(window, zoneWindow->UniqueId())) - { - m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, zoneWindow); - fancyZonesData.UpdateProcessIdToHandleMap(window, zoneWindow->UniqueId()); - } - } - } + POINT cursorPosition{}; + if (GetCursorPos(&cursorPosition)) + { + active = MonitorFromPoint(cursorPosition, MONITOR_DEFAULTTOPRIMARY); + } + + const bool primaryActive = (primary == active); + std::pair, std::vector> appZoneHistoryInfo = GetAppZoneHistoryInfo(window, active, primaryActive); + if (!appZoneHistoryInfo.second.empty()) + { + MoveWindowIntoZone(window, appZoneHistoryInfo.first, appZoneHistoryInfo.second); } } } @@ -379,7 +452,7 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept } else if ((info->vkCode == VK_RIGHT) || (info->vkCode == VK_LEFT)) { - if (ProcessSnapHotkey()) + if (ShouldProcessSnapHotkey()) { Trace::FancyZones::OnKeyDown(info->vkCode, win, ctrl, false /*inMoveSize*/); // Win+Left, Win+Right will cycle through Zones in the active ZoneSet when WM_PRIV_LOWLEVELKB's handled @@ -904,7 +977,7 @@ void FancyZones::OnEditorExitEvent() noexcept } } -bool FancyZones::ProcessSnapHotkey() noexcept +bool FancyZones::ShouldProcessSnapHotkey() noexcept { if (m_settings->GetSettings()->overrideSnapHotkeys) { diff --git a/src/modules/fancyzones/lib/util.cpp b/src/modules/fancyzones/lib/util.cpp index 6be3eeb20f..365b621028 100644 --- a/src/modules/fancyzones/lib/util.cpp +++ b/src/modules/fancyzones/lib/util.cpp @@ -4,6 +4,12 @@ #include #include +namespace +{ + const wchar_t POWER_TOYS_APP_POWER_LAUCHER[] = L"POWERLAUNCHER.EXE"; + const wchar_t POWER_TOYS_APP_FANCY_ZONES_EDITOR[] = L"FANCYZONESEDITOR.EXE"; +} + typedef BOOL(WINAPI* GetDpiForMonitorInternalFunc)(HMONITOR, UINT, UINT*, UINT*); UINT GetDpiForMonitor(HMONITOR monitor) noexcept { @@ -157,7 +163,11 @@ bool IsInterestingWindow(HWND window, const std::vector& excludedA { return false; } - if (find_app_name_in_path(filtered.process_path, { L"POWERLAUNCHER.EXE" })) + if (find_app_name_in_path(filtered.process_path, { POWER_TOYS_APP_POWER_LAUCHER })) + { + return false; + } + if (find_app_name_in_path(filtered.process_path, { POWER_TOYS_APP_FANCY_ZONES_EDITOR })) { return false; }