mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
[FancyZones] Move windows to the app last zone fix (#24290)
This commit is contained in:
@@ -37,6 +37,22 @@ enum class DisplayChangeType
|
|||||||
Initialization
|
Initialization
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr wchar_t* DisplayChangeTypeName (const DisplayChangeType type){
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DisplayChangeType::WorkArea:
|
||||||
|
return L"WorkArea";
|
||||||
|
case DisplayChangeType::DisplayChange:
|
||||||
|
return L"DisplayChange";
|
||||||
|
case DisplayChangeType::VirtualDesktop:
|
||||||
|
return L"VirtualDesktop";
|
||||||
|
case DisplayChangeType::Initialization:
|
||||||
|
return L"Initialization";
|
||||||
|
default:
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Non-localizable strings
|
// Non-localizable strings
|
||||||
namespace NonLocalizable
|
namespace NonLocalizable
|
||||||
{
|
{
|
||||||
@@ -131,13 +147,11 @@ private:
|
|||||||
bool OnSnapHotkey(DWORD vkCode) noexcept;
|
bool OnSnapHotkey(DWORD vkCode) noexcept;
|
||||||
bool ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, WorkArea* const workArea) noexcept;
|
bool ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, WorkArea* const workArea) noexcept;
|
||||||
|
|
||||||
void RegisterVirtualDesktopUpdates() noexcept;
|
void SyncVirtualDesktops() noexcept;
|
||||||
|
|
||||||
void UpdateHotkey(int hotkeyId, const PowerToysSettings::HotkeyObject& hotkeyObject, bool enable) noexcept;
|
void UpdateHotkey(int hotkeyId, const PowerToysSettings::HotkeyObject& hotkeyObject, bool enable) noexcept;
|
||||||
|
|
||||||
std::pair<WorkArea*, ZoneIndexSet> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& workAreas) noexcept;
|
bool MoveToAppLastZone(HWND window, HMONITOR monitor) noexcept;
|
||||||
void MoveWindowIntoZone(HWND window, WorkArea* const workArea, const ZoneIndexSet& zoneIndexSet) noexcept;
|
|
||||||
bool MoveToAppLastZone(HWND window, HMONITOR active, HMONITOR primary) noexcept;
|
|
||||||
|
|
||||||
void UpdateActiveLayouts() noexcept;
|
void UpdateActiveLayouts() noexcept;
|
||||||
bool ShouldProcessSnapHotkey(DWORD vkCode) noexcept;
|
bool ShouldProcessSnapHotkey(DWORD vkCode) noexcept;
|
||||||
@@ -252,7 +266,14 @@ FancyZones::Run() noexcept
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
PostMessage(m_window, WM_PRIV_VD_INIT, 0, 0);
|
SyncVirtualDesktops();
|
||||||
|
|
||||||
|
// id format of applied-layouts and app-zone-history was changed in 0.60
|
||||||
|
auto monitors = MonitorUtils::IdentifyMonitors();
|
||||||
|
AppliedLayouts::instance().AdjustWorkAreaIds(monitors);
|
||||||
|
AppZoneHistory::instance().AdjustWorkAreaIds(monitors);
|
||||||
|
|
||||||
|
PostMessage(m_window, WM_PRIV_INIT, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IFancyZones
|
// IFancyZones
|
||||||
@@ -319,64 +340,49 @@ void FancyZones::MoveSizeEnd()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<WorkArea*, ZoneIndexSet> FancyZones::GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& workAreas) noexcept
|
bool FancyZones::MoveToAppLastZone(HWND window, HMONITOR monitor) noexcept
|
||||||
{
|
|
||||||
for (const auto& [workAreaMonitor, workArea] : workAreas)
|
|
||||||
{
|
|
||||||
if (workAreaMonitor == monitor && workArea)
|
|
||||||
{
|
|
||||||
return std::pair<WorkArea*, ZoneIndexSet>{ workArea.get(), workArea->GetWindowZoneIndexes(window) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::error(L"No work area for the currently active monitor.");
|
|
||||||
return std::pair<WorkArea*, ZoneIndexSet>{ nullptr, {} };
|
|
||||||
}
|
|
||||||
|
|
||||||
void FancyZones::MoveWindowIntoZone(HWND window, WorkArea* const workArea, const ZoneIndexSet& zoneIndexSet) noexcept
|
|
||||||
{
|
|
||||||
if (workArea)
|
|
||||||
{
|
|
||||||
Trace::FancyZones::SnapNewWindowIntoZone(workArea->GetLayout().get(), workArea->GetLayoutWindows().get());
|
|
||||||
workArea->MoveWindowIntoZoneByIndexSet(window, zoneIndexSet);
|
|
||||||
AppZoneHistory::instance().UpdateProcessIdToHandleMap(window, workArea->UniqueId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FancyZones::MoveToAppLastZone(HWND window, HMONITOR active, HMONITOR primary) noexcept
|
|
||||||
{
|
{
|
||||||
const auto& workAreas = m_workAreaHandler.GetAllWorkAreas();
|
const auto& workAreas = m_workAreaHandler.GetAllWorkAreas();
|
||||||
if (workAreas.empty())
|
WorkArea* workArea{ nullptr };
|
||||||
{
|
ZoneIndexSet indexes{};
|
||||||
Logger::trace(L"No work area for the current desktop.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search application history on currently active monitor.
|
if (monitor)
|
||||||
auto appZoneHistoryInfo = GetAppZoneHistoryInfo(window, active, workAreas);
|
{
|
||||||
|
if (workAreas.contains(monitor))
|
||||||
// No application history on currently active monitor
|
{
|
||||||
if (appZoneHistoryInfo.second.empty())
|
workArea = workAreas.at(monitor).get();
|
||||||
{
|
if (workArea)
|
||||||
// Search application history on primary monitor.
|
{
|
||||||
appZoneHistoryInfo = GetAppZoneHistoryInfo(window, primary, workAreas);
|
indexes = workArea->GetWindowZoneIndexes(window);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// No application history on currently active and primary monitors
|
else
|
||||||
if (appZoneHistoryInfo.second.empty())
|
{
|
||||||
{
|
Logger::error(L"Unable to find work area for requested monitor on the active virtual desktop");
|
||||||
// Search application history on remaining monitors.
|
}
|
||||||
appZoneHistoryInfo = GetAppZoneHistoryInfo(window, nullptr, workAreas);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!appZoneHistoryInfo.second.empty())
|
|
||||||
{
|
|
||||||
MoveWindowIntoZone(window, appZoneHistoryInfo.first, appZoneHistoryInfo.second);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger::trace(L"App zone history is empty for the processing window on a current virtual desktop");
|
for (const auto& [_, secondaryWorkArea] : workAreas)
|
||||||
|
{
|
||||||
|
if (secondaryWorkArea)
|
||||||
|
{
|
||||||
|
indexes = secondaryWorkArea->GetWindowZoneIndexes(window);
|
||||||
|
workArea = secondaryWorkArea.get();
|
||||||
|
if (!indexes.empty())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!indexes.empty() && workArea)
|
||||||
|
{
|
||||||
|
Trace::FancyZones::SnapNewWindowIntoZone(workArea->GetLayout().get(), workArea->GetLayoutWindows().get());
|
||||||
|
workArea->MoveWindowIntoZoneByIndexSet(window, indexes);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -419,24 +425,35 @@ void FancyZones::WindowCreated(HWND window) noexcept
|
|||||||
active = MonitorFromPoint(cursorPosition, MONITOR_DEFAULTTOPRIMARY);
|
active = MonitorFromPoint(cursorPosition, MONITOR_DEFAULTTOPRIMARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool movedToAppLastZone = false;
|
bool windowMovedToZone = false;
|
||||||
if (FancyZonesSettings::settings().spanZonesAcrossMonitors)
|
if (moveToAppLastZone)
|
||||||
{
|
{
|
||||||
if (moveToAppLastZone)
|
if (FancyZonesSettings::settings().spanZonesAcrossMonitors)
|
||||||
{
|
{
|
||||||
movedToAppLastZone = MoveToAppLastZone(window, nullptr, nullptr);
|
windowMovedToZone = MoveToAppLastZone(window, nullptr);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
// Search application history on currently active monitor.
|
||||||
if (moveToAppLastZone)
|
windowMovedToZone = MoveToAppLastZone(window, active);
|
||||||
{
|
|
||||||
movedToAppLastZone = MoveToAppLastZone(window, active, primary);
|
if (!windowMovedToZone && primary != active)
|
||||||
|
{
|
||||||
|
// Search application history on primary monitor.
|
||||||
|
windowMovedToZone = MoveToAppLastZone(window, primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!windowMovedToZone)
|
||||||
|
{
|
||||||
|
// Search application history on remaining monitors.
|
||||||
|
windowMovedToZone = MoveToAppLastZone(window, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Open on active monitor if window wasn't zoned
|
// Open on active monitor if window wasn't zoned
|
||||||
if (openOnActiveMonitor && !movedToAppLastZone)
|
if (openOnActiveMonitor && !windowMovedToZone)
|
||||||
{
|
{
|
||||||
// window is recreated after switching virtual desktop
|
// window is recreated after switching virtual desktop
|
||||||
// avoid moving already opened windows after switching vd
|
// avoid moving already opened windows after switching vd
|
||||||
@@ -603,18 +620,16 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
{
|
{
|
||||||
OnSnapHotkey(static_cast<DWORD>(lparam));
|
OnSnapHotkey(static_cast<DWORD>(lparam));
|
||||||
}
|
}
|
||||||
else if (message == WM_PRIV_VD_INIT)
|
else if (message == WM_PRIV_INIT)
|
||||||
{
|
{
|
||||||
|
VirtualDesktop::instance().UpdateVirtualDesktopId();
|
||||||
OnDisplayChange(DisplayChangeType::Initialization);
|
OnDisplayChange(DisplayChangeType::Initialization);
|
||||||
}
|
}
|
||||||
else if (message == WM_PRIV_VD_SWITCH)
|
else if (message == WM_PRIV_VD_SWITCH)
|
||||||
{
|
{
|
||||||
|
VirtualDesktop::instance().UpdateVirtualDesktopId();
|
||||||
OnDisplayChange(DisplayChangeType::VirtualDesktop);
|
OnDisplayChange(DisplayChangeType::VirtualDesktop);
|
||||||
}
|
}
|
||||||
else if (message == WM_PRIV_VD_UPDATE)
|
|
||||||
{
|
|
||||||
OnDisplayChange(DisplayChangeType::Initialization);
|
|
||||||
}
|
|
||||||
else if (message == WM_PRIV_EDITOR)
|
else if (message == WM_PRIV_EDITOR)
|
||||||
{
|
{
|
||||||
// Clean up the event either way
|
// Clean up the event either way
|
||||||
@@ -685,27 +700,26 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
|
|
||||||
void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
||||||
{
|
{
|
||||||
Logger::info(L"Display changed, type: {}", changeType);
|
Logger::info(L"Display changed, type: {}", DisplayChangeTypeName(changeType));
|
||||||
|
|
||||||
if (changeType == DisplayChangeType::VirtualDesktop ||
|
bool updateWindowsPositions = false;
|
||||||
changeType == DisplayChangeType::Initialization)
|
|
||||||
|
switch (changeType)
|
||||||
{
|
{
|
||||||
VirtualDesktop::instance().UpdateVirtualDesktopId();
|
case DisplayChangeType::WorkArea: // WorkArea size changed
|
||||||
|
case DisplayChangeType::DisplayChange: // Resolution changed or display added
|
||||||
if (changeType == DisplayChangeType::Initialization)
|
updateWindowsPositions = FancyZonesSettings::settings().displayChange_moveWindows;
|
||||||
{
|
break;
|
||||||
RegisterVirtualDesktopUpdates();
|
case DisplayChangeType::VirtualDesktop: // Switched virtual desktop
|
||||||
|
break;
|
||||||
// id format of applied-layouts and app-zone-history was changed in 0.60
|
case DisplayChangeType::Initialization: // Initialization
|
||||||
auto monitors = MonitorUtils::IdentifyMonitors();
|
updateWindowsPositions = FancyZonesSettings::settings().zoneSetChange_moveWindows;
|
||||||
AppliedLayouts::instance().AdjustWorkAreaIds(monitors);
|
break;
|
||||||
AppZoneHistory::instance().AdjustWorkAreaIds(monitors);
|
default:
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateWindowsPositionsOnResolutionChange = FancyZonesSettings::settings().displayChange_moveWindows && changeType == DisplayChangeType::DisplayChange;
|
UpdateWorkAreas(updateWindowsPositions);
|
||||||
bool updateWindowsPositionsOnStart = FancyZonesSettings::settings().zoneSetChange_moveWindows && changeType == DisplayChangeType::Initialization;
|
|
||||||
UpdateWorkAreas(updateWindowsPositionsOnResolutionChange || updateWindowsPositionsOnStart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZones::AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id, bool updateWindowsPositions) noexcept
|
void FancyZones::AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id, bool updateWindowsPositions) noexcept
|
||||||
@@ -729,6 +743,7 @@ void FancyZones::AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAr
|
|||||||
auto workArea = WorkArea::Create(m_hinstance, id, m_workAreaHandler.GetParent(monitor), rect);
|
auto workArea = WorkArea::Create(m_hinstance, id, m_workAreaHandler.GetParent(monitor), rect);
|
||||||
if (workArea)
|
if (workArea)
|
||||||
{
|
{
|
||||||
|
workArea->InitSnappedWindows();
|
||||||
if (updateWindowsPositions)
|
if (updateWindowsPositions)
|
||||||
{
|
{
|
||||||
workArea->UpdateWindowPositions();
|
workArea->UpdateWindowPositions();
|
||||||
@@ -754,6 +769,8 @@ LRESULT CALLBACK FancyZones::s_WndProc(HWND window, UINT message, WPARAM wparam,
|
|||||||
|
|
||||||
void FancyZones::UpdateWorkAreas(bool updateWindowPositions) noexcept
|
void FancyZones::UpdateWorkAreas(bool updateWindowPositions) noexcept
|
||||||
{
|
{
|
||||||
|
Logger::debug(L"Update work areas, update windows positions: {}", updateWindowPositions);
|
||||||
|
|
||||||
m_workAreaHandler.SaveParentIds();
|
m_workAreaHandler.SaveParentIds();
|
||||||
m_workAreaHandler.Clear();
|
m_workAreaHandler.Clear();
|
||||||
|
|
||||||
@@ -1042,7 +1059,7 @@ bool FancyZones::ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZones::RegisterVirtualDesktopUpdates() noexcept
|
void FancyZones::SyncVirtualDesktops() noexcept
|
||||||
{
|
{
|
||||||
auto guids = VirtualDesktop::instance().GetVirtualDesktopIdsFromRegistry();
|
auto guids = VirtualDesktop::instance().GetVirtualDesktopIdsFromRegistry();
|
||||||
if (guids.has_value())
|
if (guids.has_value())
|
||||||
@@ -1101,7 +1118,7 @@ void FancyZones::SettingsUpdate(SettingId id)
|
|||||||
case SettingId::SpanZonesAcrossMonitors:
|
case SettingId::SpanZonesAcrossMonitors:
|
||||||
{
|
{
|
||||||
m_workAreaHandler.Clear();
|
m_workAreaHandler.Clear();
|
||||||
PostMessageW(m_window, WM_PRIV_VD_INIT, NULL, NULL);
|
PostMessageW(m_window, WM_PRIV_INIT, NULL, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::Wor
|
|||||||
|
|
||||||
bool AppZoneHistory::RemoveAppLastZone(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring_view& zoneSetId)
|
bool AppZoneHistory::RemoveAppLastZone(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring_view& zoneSetId)
|
||||||
{
|
{
|
||||||
Logger::info(L"Add app zone history, device: {}, layout: {}", workAreaId.toString(), zoneSetId);
|
Logger::info(L"Remove app zone history, device: {}, layout: {}", workAreaId.toString(), zoneSetId);
|
||||||
|
|
||||||
auto processPath = get_process_path_waiting_uwp(window);
|
auto processPath = get_process_path_waiting_uwp(window);
|
||||||
if (!processPath.empty())
|
if (!processPath.empty())
|
||||||
@@ -532,29 +532,6 @@ bool AppZoneHistory::IsAnotherWindowOfApplicationInstanceZoned(HWND window, cons
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppZoneHistory::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId)
|
|
||||||
{
|
|
||||||
auto processPath = get_process_path_waiting_uwp(window);
|
|
||||||
if (!processPath.empty())
|
|
||||||
{
|
|
||||||
auto history = m_history.find(processPath);
|
|
||||||
if (history != std::end(m_history))
|
|
||||||
{
|
|
||||||
auto& perDesktopData = history->second;
|
|
||||||
for (auto& data : perDesktopData)
|
|
||||||
{
|
|
||||||
if (data.workAreaId == workAreaId)
|
|
||||||
{
|
|
||||||
DWORD processId = 0;
|
|
||||||
GetWindowThreadProcessId(window, &processId);
|
|
||||||
data.processIdToHandleMap[processId] = window;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring& zoneSetId) const
|
ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring& zoneSetId) const
|
||||||
{
|
{
|
||||||
auto processPath = get_process_path_waiting_uwp(window);
|
auto processPath = get_process_path_waiting_uwp(window);
|
||||||
@@ -564,7 +541,6 @@ ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZone
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto srcVirtualDesktopIDStr = FancyZonesUtils::GuidToString(workAreaId.virtualDesktopId);
|
|
||||||
auto app = processPath;
|
auto app = processPath;
|
||||||
auto pos = processPath.find_last_of('\\');
|
auto pos = processPath.find_last_of('\\');
|
||||||
if (pos != std::string::npos && pos + 1 < processPath.length())
|
if (pos != std::string::npos && pos + 1 < processPath.length())
|
||||||
@@ -572,10 +548,7 @@ ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZone
|
|||||||
app = processPath.substr(pos + 1);
|
app = processPath.substr(pos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srcVirtualDesktopIDStr)
|
Logger::info(L"Get {} zone history on work area: {}", app, workAreaId.toString());
|
||||||
{
|
|
||||||
Logger::debug(L"Get {} zone history on monitor: {}, virtual desktop: {}", app, workAreaId.toString(), srcVirtualDesktopIDStr.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto history = m_history.find(processPath);
|
auto history = m_history.find(processPath);
|
||||||
if (history == std::end(m_history))
|
if (history == std::end(m_history))
|
||||||
@@ -588,14 +561,9 @@ ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZone
|
|||||||
{
|
{
|
||||||
if (data.zoneSetUuid == zoneSetId && data.workAreaId == workAreaId)
|
if (data.zoneSetUuid == zoneSetId && data.workAreaId == workAreaId)
|
||||||
{
|
{
|
||||||
auto vdStr = FancyZonesUtils::GuidToString(data.workAreaId.virtualDesktopId);
|
|
||||||
if (vdStr)
|
|
||||||
{
|
|
||||||
Logger::debug(L"App zone history found on the device {} with virtual desktop {}", data.workAreaId.toString(), vdStr.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.workAreaId.virtualDesktopId == workAreaId.virtualDesktopId || data.workAreaId.virtualDesktopId == GUID_NULL)
|
if (data.workAreaId.virtualDesktopId == workAreaId.virtualDesktopId || data.workAreaId.virtualDesktopId == GUID_NULL)
|
||||||
{
|
{
|
||||||
|
Logger::info(L"App zone history found on the work area {}", data.workAreaId.toString());
|
||||||
return data.zoneIndexSet;
|
return data.zoneIndexSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ public:
|
|||||||
std::optional<FancyZonesDataTypes::AppZoneHistoryData> GetZoneHistory(const std::wstring& appPath, const FancyZonesDataTypes::WorkAreaId& workAreaId) const noexcept;
|
std::optional<FancyZonesDataTypes::AppZoneHistoryData> GetZoneHistory(const std::wstring& appPath, const FancyZonesDataTypes::WorkAreaId& workAreaId) const noexcept;
|
||||||
|
|
||||||
bool IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId) const noexcept;
|
bool IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId) const noexcept;
|
||||||
void UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId);
|
|
||||||
ZoneIndexSet GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring& zoneSetId) const;
|
ZoneIndexSet GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring& zoneSetId) const;
|
||||||
|
|
||||||
void SyncVirtualDesktops();
|
void SyncVirtualDesktops();
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ UINT WM_PRIV_MOVESIZEEND;
|
|||||||
UINT WM_PRIV_LOCATIONCHANGE;
|
UINT WM_PRIV_LOCATIONCHANGE;
|
||||||
UINT WM_PRIV_NAMECHANGE;
|
UINT WM_PRIV_NAMECHANGE;
|
||||||
UINT WM_PRIV_WINDOWCREATED;
|
UINT WM_PRIV_WINDOWCREATED;
|
||||||
UINT WM_PRIV_VD_INIT;
|
UINT WM_PRIV_INIT;
|
||||||
UINT WM_PRIV_VD_SWITCH;
|
UINT WM_PRIV_VD_SWITCH;
|
||||||
UINT WM_PRIV_VD_UPDATE;
|
|
||||||
UINT WM_PRIV_EDITOR;
|
UINT WM_PRIV_EDITOR;
|
||||||
UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE;
|
UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE;
|
||||||
UINT WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE;
|
UINT WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE;
|
||||||
@@ -30,9 +29,8 @@ void InitializeWinhookEventIds()
|
|||||||
WM_PRIV_LOCATIONCHANGE = RegisterWindowMessage(L"{d56c5ee7-58e5-481c-8c4f-8844cf4d0347}");
|
WM_PRIV_LOCATIONCHANGE = RegisterWindowMessage(L"{d56c5ee7-58e5-481c-8c4f-8844cf4d0347}");
|
||||||
WM_PRIV_NAMECHANGE = RegisterWindowMessage(L"{b7b30c61-bfa0-4d95-bcde-fc4f2cbf6d76}");
|
WM_PRIV_NAMECHANGE = RegisterWindowMessage(L"{b7b30c61-bfa0-4d95-bcde-fc4f2cbf6d76}");
|
||||||
WM_PRIV_WINDOWCREATED = RegisterWindowMessage(L"{bdb10669-75da-480a-9ec4-eeebf09a02d7}");
|
WM_PRIV_WINDOWCREATED = RegisterWindowMessage(L"{bdb10669-75da-480a-9ec4-eeebf09a02d7}");
|
||||||
WM_PRIV_VD_INIT = RegisterWindowMessage(L"{469818a8-00fa-4069-b867-a1da484fcd9a}");
|
WM_PRIV_INIT = RegisterWindowMessage(L"{469818a8-00fa-4069-b867-a1da484fcd9a}");
|
||||||
WM_PRIV_VD_SWITCH = RegisterWindowMessage(L"{128c2cb0-6bdf-493e-abbe-f8705e04aa95}");
|
WM_PRIV_VD_SWITCH = RegisterWindowMessage(L"{128c2cb0-6bdf-493e-abbe-f8705e04aa95}");
|
||||||
WM_PRIV_VD_UPDATE = RegisterWindowMessage(L"{b8b72b46-f42f-4c26-9e20-29336cf2f22e}");
|
|
||||||
WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
||||||
WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE = RegisterWindowMessage(L"{07229b7e-4f22-4357-b136-33c289be2295}");
|
WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE = RegisterWindowMessage(L"{07229b7e-4f22-4357-b136-33c289be2295}");
|
||||||
WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE = RegisterWindowMessage(L"{4686f019-5d3d-4c5c-9051-b7cbbccca77d}");
|
WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE = RegisterWindowMessage(L"{4686f019-5d3d-4c5c-9051-b7cbbccca77d}");
|
||||||
|
|||||||
@@ -5,9 +5,8 @@ extern UINT WM_PRIV_MOVESIZEEND;
|
|||||||
extern UINT WM_PRIV_LOCATIONCHANGE;
|
extern UINT WM_PRIV_LOCATIONCHANGE;
|
||||||
extern UINT WM_PRIV_NAMECHANGE;
|
extern UINT WM_PRIV_NAMECHANGE;
|
||||||
extern UINT WM_PRIV_WINDOWCREATED;
|
extern UINT WM_PRIV_WINDOWCREATED;
|
||||||
extern UINT WM_PRIV_VD_INIT; // Scheduled when FancyZones is initialized
|
extern UINT WM_PRIV_INIT; // Scheduled when FancyZones is initialized
|
||||||
extern UINT WM_PRIV_VD_SWITCH; // Scheduled when virtual desktop switch occurs
|
extern UINT WM_PRIV_VD_SWITCH; // Scheduled when virtual desktop switch occurs
|
||||||
extern UINT WM_PRIV_VD_UPDATE; // Scheduled on virtual desktops update (creation/deletion)
|
|
||||||
extern UINT WM_PRIV_EDITOR; // Scheduled when the editor exits
|
extern UINT WM_PRIV_EDITOR; // Scheduled when the editor exits
|
||||||
extern UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE; // Scheduled when the watched layout-hotkeys.json file is updated
|
extern UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE; // Scheduled when the watched layout-hotkeys.json file is updated
|
||||||
extern UINT WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE; // Scheduled when the watched layout-templates.json file is updated
|
extern UINT WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE; // Scheduled when the watched layout-templates.json file is updated
|
||||||
|
|||||||
@@ -405,6 +405,16 @@ void WorkArea::UnsnapWindow(HWND window)
|
|||||||
FancyZonesWindowProperties::RemoveZoneIndexProperty(window);
|
FancyZonesWindowProperties::RemoveZoneIndexProperty(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GUID WorkArea::GetLayoutId() const noexcept
|
||||||
|
{
|
||||||
|
if (m_layout)
|
||||||
|
{
|
||||||
|
return m_layout->Id();
|
||||||
|
}
|
||||||
|
|
||||||
|
return GUID{};
|
||||||
|
}
|
||||||
|
|
||||||
ZoneIndexSet WorkArea::GetWindowZoneIndexes(HWND window) const
|
ZoneIndexSet WorkArea::GetWindowZoneIndexes(HWND window) const
|
||||||
{
|
{
|
||||||
if (m_layout)
|
if (m_layout)
|
||||||
@@ -529,26 +539,36 @@ void WorkArea::InitLayout(const FancyZonesDataTypes::WorkAreaId& parentUniqueId)
|
|||||||
|
|
||||||
void WorkArea::InitSnappedWindows()
|
void WorkArea::InitSnappedWindows()
|
||||||
{
|
{
|
||||||
Logger::info(L"Init work area windows");
|
Logger::info(L"Init work area windows: {}", m_uniqueId.toString());
|
||||||
|
|
||||||
for (const auto& window : VirtualDesktop::instance().GetWindowsFromCurrentDesktop())
|
for (const auto& window : VirtualDesktop::instance().GetWindowsFromCurrentDesktop())
|
||||||
{
|
{
|
||||||
auto zoneIndexSet = FancyZonesWindowProperties::RetrieveZoneIndexProperty(window);
|
auto indexes = FancyZonesWindowProperties::RetrieveZoneIndexProperty(window);
|
||||||
if (zoneIndexSet.size() == 0)
|
if (indexes.size() == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_uniqueId.monitorId.monitor) // one work area across monitors
|
if (!m_uniqueId.monitorId.monitor) // one work area across monitors
|
||||||
{
|
{
|
||||||
MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, false);
|
MoveWindowIntoZoneByIndexSet(window, indexes, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
|
const auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
|
||||||
if (monitor && m_uniqueId.monitorId.monitor == monitor)
|
if (monitor && m_uniqueId.monitorId.monitor == monitor)
|
||||||
{
|
{
|
||||||
MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, false);
|
// prioritize snapping on the current monitor if the window was snapped to several work areas
|
||||||
|
MoveWindowIntoZoneByIndexSet(window, indexes, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if the window is not snapped on the current monitor, then check the others
|
||||||
|
auto savedIndexes = GetWindowZoneIndexes(window);
|
||||||
|
if (savedIndexes == indexes)
|
||||||
|
{
|
||||||
|
MoveWindowIntoZoneByIndexSet(window, indexes, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
InitLayout(parentUniqueId);
|
InitLayout(parentUniqueId);
|
||||||
InitSnappedWindows();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +41,7 @@ public:
|
|||||||
const std::unique_ptr<Layout>& GetLayout() const noexcept { return m_layout; }
|
const std::unique_ptr<Layout>& GetLayout() const noexcept { return m_layout; }
|
||||||
const std::unique_ptr<LayoutAssignedWindows>& GetLayoutWindows() const noexcept { return m_layoutWindows; }
|
const std::unique_ptr<LayoutAssignedWindows>& GetLayoutWindows() const noexcept { return m_layoutWindows; }
|
||||||
const HWND GetWorkAreaWindow() const noexcept { return m_window; }
|
const HWND GetWorkAreaWindow() const noexcept { return m_window; }
|
||||||
|
const GUID GetLayoutId() const noexcept;
|
||||||
|
|
||||||
ZoneIndexSet GetWindowZoneIndexes(HWND window) const;
|
ZoneIndexSet GetWindowZoneIndexes(HWND window) const;
|
||||||
|
|
||||||
@@ -51,6 +51,7 @@ public:
|
|||||||
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle);
|
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle);
|
||||||
bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode);
|
bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode);
|
||||||
|
|
||||||
|
void InitSnappedWindows();
|
||||||
void SnapWindow(HWND window, const ZoneIndexSet& zones, bool extend = false);
|
void SnapWindow(HWND window, const ZoneIndexSet& zones, bool extend = false);
|
||||||
void UnsnapWindow(HWND window);
|
void UnsnapWindow(HWND window);
|
||||||
|
|
||||||
@@ -69,8 +70,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool InitWindow(HINSTANCE hinstance);
|
bool InitWindow(HINSTANCE hinstance);
|
||||||
void InitLayout(const FancyZonesDataTypes::WorkAreaId& parentUniqueId);
|
void InitLayout(const FancyZonesDataTypes::WorkAreaId& parentUniqueId);
|
||||||
void InitSnappedWindows();
|
|
||||||
|
|
||||||
void CalculateZoneSet();
|
void CalculateZoneSet();
|
||||||
void SetWorkAreaWindowAsTopmost(HWND draggedWindow) noexcept;
|
void SetWorkAreaWindowAsTopmost(HWND draggedWindow) noexcept;
|
||||||
|
|
||||||
|
|||||||
@@ -460,7 +460,7 @@ namespace FancyZonesUnitTests
|
|||||||
PrepareGridLayout();
|
PrepareGridLayout();
|
||||||
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
||||||
const auto window = Mocks::WindowCreate(m_hInst);
|
const auto window = Mocks::WindowCreate(m_hInst);
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true); // apply to 1st zone
|
workArea->MoveWindowIntoZoneByIndexSet(window, { 0 }, true); // snap to the 1st zone
|
||||||
|
|
||||||
// test
|
// test
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndPosition(window, VK_RIGHT, true);
|
workArea->MoveWindowIntoZoneByDirectionAndPosition(window, VK_RIGHT, true);
|
||||||
@@ -478,7 +478,7 @@ namespace FancyZonesUnitTests
|
|||||||
PrepareGridLayout();
|
PrepareGridLayout();
|
||||||
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
||||||
const auto window = Mocks::WindowCreate(m_hInst);
|
const auto window = Mocks::WindowCreate(m_hInst);
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true); // apply to 1st zone
|
workArea->MoveWindowIntoZoneByIndexSet(window, { 0 }, true); // snap to the 1st zone
|
||||||
|
|
||||||
// test
|
// test
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndPosition(window, VK_DOWN, true);
|
workArea->MoveWindowIntoZoneByDirectionAndPosition(window, VK_DOWN, true);
|
||||||
@@ -496,7 +496,7 @@ namespace FancyZonesUnitTests
|
|||||||
PrepareGridLayout();
|
PrepareGridLayout();
|
||||||
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
||||||
const auto window = Mocks::WindowCreate(m_hInst);
|
const auto window = Mocks::WindowCreate(m_hInst);
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true); // apply to 1st zone
|
workArea->MoveWindowIntoZoneByIndexSet(window, { 0 }, true); // snap to the 1st zone
|
||||||
|
|
||||||
// test
|
// test
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndPosition(window, VK_LEFT, true);
|
workArea->MoveWindowIntoZoneByDirectionAndPosition(window, VK_LEFT, true);
|
||||||
@@ -533,7 +533,7 @@ namespace FancyZonesUnitTests
|
|||||||
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
||||||
const auto window = Mocks::WindowCreate(m_hInst);
|
const auto window = Mocks::WindowCreate(m_hInst);
|
||||||
const auto& layoutWindows = workArea->GetLayoutWindows();
|
const auto& layoutWindows = workArea->GetLayoutWindows();
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true); // apply to 1st zone
|
workArea->MoveWindowIntoZoneByIndexSet(window, { 0 }, true); // snap to the 1st zone
|
||||||
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows->GetZoneIndexSetFromWindow(window));
|
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows->GetZoneIndexSetFromWindow(window));
|
||||||
|
|
||||||
// test
|
// test
|
||||||
@@ -551,7 +551,7 @@ namespace FancyZonesUnitTests
|
|||||||
PrepareGridLayout();
|
PrepareGridLayout();
|
||||||
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
||||||
const auto window = Mocks::WindowCreate(m_hInst);
|
const auto window = Mocks::WindowCreate(m_hInst);
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true); // apply to 1st zone
|
workArea->MoveWindowIntoZoneByIndexSet(window, { 0 }, true); // snap to the 1st zone
|
||||||
|
|
||||||
// test
|
// test
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndPosition(window, VK_UP, false);
|
workArea->MoveWindowIntoZoneByDirectionAndPosition(window, VK_UP, false);
|
||||||
@@ -569,7 +569,7 @@ namespace FancyZonesUnitTests
|
|||||||
PrepareGridLayout();
|
PrepareGridLayout();
|
||||||
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
||||||
const auto window = Mocks::WindowCreate(m_hInst);
|
const auto window = Mocks::WindowCreate(m_hInst);
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true); // apply to 1st zone
|
workArea->MoveWindowIntoZoneByIndexSet(window, { 0 }, true); // snap to the 1st zone
|
||||||
|
|
||||||
// test
|
// test
|
||||||
workArea->ExtendWindowByDirectionAndPosition(window, VK_RIGHT);
|
workArea->ExtendWindowByDirectionAndPosition(window, VK_RIGHT);
|
||||||
@@ -587,7 +587,7 @@ namespace FancyZonesUnitTests
|
|||||||
PrepareGridLayout();
|
PrepareGridLayout();
|
||||||
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
||||||
const auto window = Mocks::WindowCreate(m_hInst);
|
const auto window = Mocks::WindowCreate(m_hInst);
|
||||||
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true); // apply to 1st zone
|
workArea->MoveWindowIntoZoneByIndexSet(window, { 0 }, true); // snap to the 1st zone
|
||||||
|
|
||||||
// test
|
// test
|
||||||
workArea->ExtendWindowByDirectionAndPosition(window, VK_DOWN);
|
workArea->ExtendWindowByDirectionAndPosition(window, VK_DOWN);
|
||||||
|
|||||||
Reference in New Issue
Block a user