mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 09:28:03 +08:00
[FancyZones] Outlook new message restore placement bug (#2534)
This commit is contained in:
parent
3265549911
commit
3d619f1670
@ -60,13 +60,13 @@ public:
|
|||||||
std::unique_lock writeLock(m_lock);
|
std::unique_lock writeLock(m_lock);
|
||||||
m_windowMoveHandler.MoveSizeStart(window, monitor, ptScreen, m_zoneWindowMap);
|
m_windowMoveHandler.MoveSizeStart(window, monitor, ptScreen, m_zoneWindowMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen) noexcept
|
void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen) noexcept
|
||||||
{
|
{
|
||||||
std::unique_lock writeLock(m_lock);
|
std::unique_lock writeLock(m_lock);
|
||||||
m_windowMoveHandler.MoveSizeUpdate(monitor, ptScreen, m_zoneWindowMap);
|
m_windowMoveHandler.MoveSizeUpdate(monitor, ptScreen, m_zoneWindowMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept
|
void MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept
|
||||||
{
|
{
|
||||||
std::unique_lock writeLock(m_lock);
|
std::unique_lock writeLock(m_lock);
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
ToggleEditor() noexcept;
|
ToggleEditor() noexcept;
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
SettingsChanged() noexcept;
|
SettingsChanged() noexcept;
|
||||||
|
|
||||||
void WindowCreated(HWND window) noexcept;
|
void WindowCreated(HWND window) noexcept;
|
||||||
|
|
||||||
// IZoneWindowHost
|
// IZoneWindowHost
|
||||||
@ -222,9 +222,12 @@ private:
|
|||||||
bool OnSnapHotkey(DWORD vkCode) noexcept;
|
bool OnSnapHotkey(DWORD vkCode) noexcept;
|
||||||
|
|
||||||
void RegisterVirtualDesktopUpdates(std::vector<GUID>& ids) noexcept;
|
void RegisterVirtualDesktopUpdates(std::vector<GUID>& ids) noexcept;
|
||||||
|
|
||||||
void RegisterNewWorkArea(GUID virtualDesktopId, HMONITOR monitor) noexcept;
|
void RegisterNewWorkArea(GUID virtualDesktopId, HMONITOR monitor) noexcept;
|
||||||
bool IsNewWorkArea(GUID virtualDesktopId, HMONITOR monitor) noexcept;
|
bool IsNewWorkArea(GUID virtualDesktopId, HMONITOR monitor) noexcept;
|
||||||
|
|
||||||
|
bool IsSplashScreen(HWND window);
|
||||||
|
|
||||||
void OnEditorExitEvent() noexcept;
|
void OnEditorExitEvent() noexcept;
|
||||||
bool ProcessSnapHotkey() noexcept;
|
bool ProcessSnapHotkey() noexcept;
|
||||||
|
|
||||||
@ -340,6 +343,7 @@ IFACEMETHODIMP_(void)
|
|||||||
FancyZones::WindowCreated(HWND window) noexcept
|
FancyZones::WindowCreated(HWND window) noexcept
|
||||||
{
|
{
|
||||||
std::shared_lock readLock(m_lock);
|
std::shared_lock readLock(m_lock);
|
||||||
|
|
||||||
if (m_settings->GetSettings()->appLastZone_moveWindows && IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray))
|
if (m_settings->GetSettings()->appLastZone_moveWindows && IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray))
|
||||||
{
|
{
|
||||||
for (const auto& [monitor, zoneWindow] : m_zoneWindowMap)
|
for (const auto& [monitor, zoneWindow] : m_zoneWindowMap)
|
||||||
@ -357,15 +361,18 @@ FancyZones::WindowCreated(HWND window) noexcept
|
|||||||
const auto activeZoneSet = zoneWindow->ActiveZoneSet();
|
const auto activeZoneSet = zoneWindow->ActiveZoneSet();
|
||||||
if (activeZoneSet)
|
if (activeZoneSet)
|
||||||
{
|
{
|
||||||
const auto& fancyZonesData = JSONHelpers::FancyZonesDataInstance();
|
auto& fancyZonesData = JSONHelpers::FancyZonesDataInstance();
|
||||||
|
|
||||||
wil::unique_cotaskmem_string guidString;
|
wil::unique_cotaskmem_string guidString;
|
||||||
if (SUCCEEDED(StringFromCLSID(activeZoneSet->Id(), &guidString)))
|
if (SUCCEEDED(StringFromCLSID(activeZoneSet->Id(), &guidString)))
|
||||||
{
|
{
|
||||||
std::vector<int> zoneIndexSet = fancyZonesData.GetAppLastZoneIndexSet(window, zoneWindow->UniqueId(), guidString.get());
|
std::vector<int> zoneIndexSet = fancyZonesData.GetAppLastZoneIndexSet(window, zoneWindow->UniqueId(), guidString.get());
|
||||||
if (zoneIndexSet.size())
|
if (zoneIndexSet.size() &&
|
||||||
|
!IsSplashScreen(window) &&
|
||||||
|
!fancyZonesData.IsAnotherWindowOfApplicationInstanceZoned(window))
|
||||||
{
|
{
|
||||||
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, monitor, zoneIndexSet, m_zoneWindowMap);
|
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, monitor, zoneIndexSet, m_zoneWindowMap);
|
||||||
|
fancyZonesData.UpdateProcessIdToHandleMap(window);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -662,7 +669,6 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
||||||
{
|
{
|
||||||
if (changeType == DisplayChangeType::VirtualDesktop ||
|
if (changeType == DisplayChangeType::VirtualDesktop ||
|
||||||
@ -932,6 +938,18 @@ bool FancyZones::IsNewWorkArea(GUID virtualDesktopId, HMONITOR monitor) noexcept
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FancyZones::IsSplashScreen(HWND window)
|
||||||
|
{
|
||||||
|
wchar_t splashClassName[] = L"MsoSplash"; // shouldn't be localized
|
||||||
|
wchar_t className[MAX_PATH];
|
||||||
|
if (GetClassName(window, className, MAX_PATH) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wcscmp(splashClassName, className) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
void FancyZones::OnEditorExitEvent() noexcept
|
void FancyZones::OnEditorExitEvent() noexcept
|
||||||
{
|
{
|
||||||
// Collect information about changes in zone layout after editor exited.
|
// Collect information about changes in zone layout after editor exited.
|
||||||
|
@ -382,6 +382,51 @@ namespace JSONHelpers
|
|||||||
SaveFancyZonesData();
|
SaveFancyZonesData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FancyZonesData::IsAnotherWindowOfApplicationInstanceZoned(HWND window) const
|
||||||
|
{
|
||||||
|
std::scoped_lock lock{ dataLock };
|
||||||
|
auto processPath = get_process_path(window);
|
||||||
|
if (!processPath.empty())
|
||||||
|
{
|
||||||
|
auto history = appZoneHistoryMap.find(processPath);
|
||||||
|
if (history != appZoneHistoryMap.end())
|
||||||
|
{
|
||||||
|
DWORD processId = 0;
|
||||||
|
GetWindowThreadProcessId(window, &processId);
|
||||||
|
|
||||||
|
auto processIdIt = history->second.processIdToHandleMap.find(processId);
|
||||||
|
|
||||||
|
if (processIdIt == history->second.processIdToHandleMap.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (processIdIt->second != window && IsWindow(processIdIt->second))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FancyZonesData::UpdateProcessIdToHandleMap(HWND window)
|
||||||
|
{
|
||||||
|
std::scoped_lock lock{ dataLock };
|
||||||
|
auto processPath = get_process_path(window);
|
||||||
|
if (!processPath.empty())
|
||||||
|
{
|
||||||
|
auto history = appZoneHistoryMap.find(processPath);
|
||||||
|
if (history != appZoneHistoryMap.end())
|
||||||
|
{
|
||||||
|
DWORD processId = 0;
|
||||||
|
GetWindowThreadProcessId(window, &processId);
|
||||||
|
|
||||||
|
history->second.processIdToHandleMap[processId] = window;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<int> FancyZonesData::GetAppLastZoneIndexSet(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const
|
std::vector<int> FancyZonesData::GetAppLastZoneIndexSet(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{ dataLock };
|
std::scoped_lock lock{ dataLock };
|
||||||
@ -411,9 +456,26 @@ namespace JSONHelpers
|
|||||||
auto history = appZoneHistoryMap.find(processPath);
|
auto history = appZoneHistoryMap.find(processPath);
|
||||||
if (history != appZoneHistoryMap.end())
|
if (history != appZoneHistoryMap.end())
|
||||||
{
|
{
|
||||||
const auto& data = history->second;
|
auto& data = history->second;
|
||||||
if (data.zoneSetUuid == zoneSetId && data.deviceId == deviceId)
|
if (data.zoneSetUuid == zoneSetId && data.deviceId == deviceId)
|
||||||
{
|
{
|
||||||
|
if (!IsAnotherWindowOfApplicationInstanceZoned(window))
|
||||||
|
{
|
||||||
|
DWORD processId = 0;
|
||||||
|
GetWindowThreadProcessId(window, &processId);
|
||||||
|
|
||||||
|
data.processIdToHandleMap.erase(processId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is another instance placed don't erase history
|
||||||
|
for (auto placedWindow : data.processIdToHandleMap)
|
||||||
|
{
|
||||||
|
if (IsWindow(placedWindow.second))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
appZoneHistoryMap.erase(processPath);
|
appZoneHistoryMap.erase(processPath);
|
||||||
SaveFancyZonesData();
|
SaveFancyZonesData();
|
||||||
return true;
|
return true;
|
||||||
@ -427,13 +489,39 @@ namespace JSONHelpers
|
|||||||
bool FancyZonesData::SetAppLastZones(HWND window, const std::wstring& deviceId, const std::wstring& zoneSetId, const std::vector<int>& zoneIndexSet)
|
bool FancyZonesData::SetAppLastZones(HWND window, const std::wstring& deviceId, const std::wstring& zoneSetId, const std::vector<int>& zoneIndexSet)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{ dataLock };
|
std::scoped_lock lock{ dataLock };
|
||||||
|
|
||||||
|
if (IsAnotherWindowOfApplicationInstanceZoned(window))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto processPath = get_process_path(window);
|
auto processPath = get_process_path(window);
|
||||||
if (processPath.empty())
|
if (processPath.empty())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
appZoneHistoryMap[processPath] = AppZoneHistoryData{ .zoneSetUuid = zoneSetId, .deviceId = deviceId, .zoneIndexSet = zoneIndexSet };
|
DWORD processId = 0;
|
||||||
|
GetWindowThreadProcessId(window, &processId);
|
||||||
|
|
||||||
|
auto history = appZoneHistoryMap.find(processPath);
|
||||||
|
|
||||||
|
if (history != appZoneHistoryMap.end())
|
||||||
|
{
|
||||||
|
auto& data = history->second;
|
||||||
|
|
||||||
|
for (auto placedWindow : data.processIdToHandleMap)
|
||||||
|
{
|
||||||
|
if (IsWindow(placedWindow.second) && processId != placedWindow.first)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto windowMap = appZoneHistoryMap[processPath].processIdToHandleMap;
|
||||||
|
windowMap[processId] = window;
|
||||||
|
appZoneHistoryMap[processPath] = AppZoneHistoryData{ .processIdToHandleMap = windowMap, .zoneSetUuid = zoneSetId, .deviceId = deviceId, .zoneIndexSet = zoneIndexSet };
|
||||||
SaveFancyZonesData();
|
SaveFancyZonesData();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -735,18 +823,19 @@ namespace JSONHelpers
|
|||||||
|
|
||||||
switch (zoneSetData.type)
|
switch (zoneSetData.type)
|
||||||
{
|
{
|
||||||
case CustomLayoutType::Grid: {
|
case CustomLayoutType::Grid:
|
||||||
|
{
|
||||||
int j = 5;
|
int j = 5;
|
||||||
GridLayoutInfo zoneSetInfo(GridLayoutInfo::Minimal{ .rows = data[j++], .columns = data[j++] });
|
GridLayoutInfo zoneSetInfo(GridLayoutInfo::Minimal{ .rows = data[j++], .columns = data[j++] });
|
||||||
|
|
||||||
for (int row = 0; row < zoneSetInfo.rows(); row++, j+=2)
|
for (int row = 0; row < zoneSetInfo.rows(); row++, j += 2)
|
||||||
{
|
{
|
||||||
zoneSetInfo.rowsPercents()[row] = data[j] * 256 + data[j+1];
|
zoneSetInfo.rowsPercents()[row] = data[j] * 256 + data[j + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int col = 0; col < zoneSetInfo.columns(); col++, j+=2)
|
for (int col = 0; col < zoneSetInfo.columns(); col++, j += 2)
|
||||||
{
|
{
|
||||||
zoneSetInfo.columnsPercents()[col] = data[j] * 256 + data[j+1];
|
zoneSetInfo.columnsPercents()[col] = data[j] * 256 + data[j + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int row = 0; row < zoneSetInfo.rows(); row++)
|
for (int row = 0; row < zoneSetInfo.rows(); row++)
|
||||||
@ -759,7 +848,8 @@ namespace JSONHelpers
|
|||||||
zoneSetData.info = zoneSetInfo;
|
zoneSetData.info = zoneSetInfo;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CustomLayoutType::Canvas: {
|
case CustomLayoutType::Canvas:
|
||||||
|
{
|
||||||
CanvasLayoutInfo info;
|
CanvasLayoutInfo info;
|
||||||
|
|
||||||
int j = 5;
|
int j = 5;
|
||||||
@ -1071,7 +1161,8 @@ namespace JSONHelpers
|
|||||||
result.SetNamedValue(L"name", json::value(customZoneSet.data.name));
|
result.SetNamedValue(L"name", json::value(customZoneSet.data.name));
|
||||||
switch (customZoneSet.data.type)
|
switch (customZoneSet.data.type)
|
||||||
{
|
{
|
||||||
case CustomLayoutType::Canvas: {
|
case CustomLayoutType::Canvas:
|
||||||
|
{
|
||||||
result.SetNamedValue(L"type", json::value(L"canvas"));
|
result.SetNamedValue(L"type", json::value(L"canvas"));
|
||||||
|
|
||||||
CanvasLayoutInfo info = std::get<CanvasLayoutInfo>(customZoneSet.data.info);
|
CanvasLayoutInfo info = std::get<CanvasLayoutInfo>(customZoneSet.data.info);
|
||||||
@ -1079,7 +1170,8 @@ namespace JSONHelpers
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CustomLayoutType::Grid: {
|
case CustomLayoutType::Grid:
|
||||||
|
{
|
||||||
result.SetNamedValue(L"type", json::value(L"grid"));
|
result.SetNamedValue(L"type", json::value(L"grid"));
|
||||||
|
|
||||||
GridLayoutInfo gridInfo = std::get<GridLayoutInfo>(customZoneSet.data.info);
|
GridLayoutInfo gridInfo = std::get<GridLayoutInfo>(customZoneSet.data.info);
|
||||||
@ -1103,7 +1195,7 @@ namespace JSONHelpers
|
|||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.data.name = customZoneSet.GetNamedString(L"name");
|
result.data.name = customZoneSet.GetNamedString(L"name");
|
||||||
|
|
||||||
json::JsonObject infoJson = customZoneSet.GetNamedObject(L"info");
|
json::JsonObject infoJson = customZoneSet.GetNamedObject(L"info");
|
||||||
|
@ -132,6 +132,8 @@ namespace JSONHelpers
|
|||||||
|
|
||||||
struct AppZoneHistoryData
|
struct AppZoneHistoryData
|
||||||
{
|
{
|
||||||
|
std::map<DWORD, HWND> processIdToHandleMap; // Maps process id(DWORD) of application to zoned window handle(HWND)
|
||||||
|
|
||||||
std::wstring zoneSetUuid;
|
std::wstring zoneSetUuid;
|
||||||
std::wstring deviceId;
|
std::wstring deviceId;
|
||||||
std::vector<int> zoneIndexSet;
|
std::vector<int> zoneIndexSet;
|
||||||
@ -242,6 +244,8 @@ namespace JSONHelpers
|
|||||||
void UpdatePrimaryDesktopData(const std::wstring& desktopId);
|
void UpdatePrimaryDesktopData(const std::wstring& desktopId);
|
||||||
void RemoveDeletedDesktops(const std::vector<std::wstring>& activeDesktops);
|
void RemoveDeletedDesktops(const std::vector<std::wstring>& activeDesktops);
|
||||||
|
|
||||||
|
bool IsAnotherWindowOfApplicationInstanceZoned(HWND window) const;
|
||||||
|
void UpdateProcessIdToHandleMap(HWND window);
|
||||||
std::vector<int> GetAppLastZoneIndexSet(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const;
|
std::vector<int> GetAppLastZoneIndexSet(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const;
|
||||||
bool RemoveAppLastZone(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId);
|
bool RemoveAppLastZone(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId);
|
||||||
bool SetAppLastZones(HWND window, const std::wstring& deviceId, const std::wstring& zoneSetId, const std::vector<int>& zoneIndexSet);
|
bool SetAppLastZones(HWND window, const std::wstring& deviceId, const std::wstring& zoneSetId, const std::vector<int>& zoneIndexSet);
|
||||||
|
Loading…
Reference in New Issue
Block a user