[FancyZones] Do not zone window if it should be maximized (#6619)

* Do not zone window if it should be maximized

* Update comment

* Remove uneeded field

* Address PR comment
This commit is contained in:
stefansjfw 2020-09-15 13:03:17 +02:00 committed by GitHub
parent eaf54ca525
commit 3d36779e19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 59 deletions

View file

@ -52,6 +52,15 @@ namespace WindowMoveHandlerUtils
} }
return false; return false;
} }
// MoveSize related window properties
struct MoveSizeWindowInfo
{
// True if from the styles the window looks like a standard window
bool standardWindow = false;
// True if the window is a top-level window that does not have a visible owner
bool noVisibleOwner = false;
};
} }
class WindowMoveHandlerPrivate class WindowMoveHandlerPrivate
@ -104,7 +113,7 @@ private:
HWND m_windowMoveSize{}; // The window that is being moved/sized HWND m_windowMoveSize{}; // The window that is being moved/sized
bool m_inMoveSize{}; // Whether or not a move/size operation is currently active bool m_inMoveSize{}; // Whether or not a move/size operation is currently active
FancyZonesUtils::FancyZonesWindowInfo m_moveSizeStartWindowInfo; // WindowInfo of the window at the moment when dragging started WindowMoveHandlerUtils::MoveSizeWindowInfo m_moveSizeWindowInfo; // MoveSizeWindowInfo of the window at the moment when dragging started
winrt::com_ptr<IZoneWindow> m_zoneWindowMoveSize; // "Active" ZoneWindow, where the move/size is happening. Will update as drag moves between monitors. winrt::com_ptr<IZoneWindow> m_zoneWindowMoveSize; // "Active" ZoneWindow, where the move/size is happening. Will update as drag moves between monitors.
bool m_dragEnabled{}; // True if we should be showing zone hints while dragging bool m_dragEnabled{}; // True if we should be showing zone hints while dragging
@ -184,7 +193,8 @@ void WindowMoveHandlerPrivate::MoveSizeStart(HWND window, HMONITOR monitor, POIN
return; return;
} }
m_moveSizeStartWindowInfo = FancyZonesUtils::GetFancyZonesWindowInfo(window); m_moveSizeWindowInfo.noVisibleOwner = FancyZonesUtils::HasNoVisibleOwner(window);
m_moveSizeWindowInfo.standardWindow = FancyZonesUtils::IsStandardWindow(window);
m_inMoveSize = true; m_inMoveSize = true;
auto iter = zoneWindowMap.find(monitor); auto iter = zoneWindowMap.find(monitor);
@ -325,12 +335,15 @@ void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, c
auto zoneWindow = std::move(m_zoneWindowMoveSize); auto zoneWindow = std::move(m_zoneWindowMoveSize);
ResetWindowTransparency(); ResetWindowTransparency();
auto windowInfo = FancyZonesUtils::GetFancyZonesWindowInfo(window); bool hasNoVisibleOwnoer = FancyZonesUtils::HasNoVisibleOwner(window);
bool isStandardWindow = FancyZonesUtils::IsStandardWindow(window);
if (windowInfo.standardWindow == false && windowInfo.noVisibleOwner == false && if ((isStandardWindow == false && hasNoVisibleOwnoer == false &&
m_moveSizeStartWindowInfo.standardWindow == true && m_moveSizeStartWindowInfo.noVisibleOwner == true) m_moveSizeWindowInfo.standardWindow == true && m_moveSizeWindowInfo.noVisibleOwner == true) ||
FancyZonesUtils::IsWindowMaximized(window))
{ {
// Abort the zoning, this is a Chromium based tab that is merged back with an existing window // Abort the zoning, this is a Chromium based tab that is merged back with an existing window
// or if the window is maximized by Windows when the cursor hits the screen top border
} }
else else
{ {

View file

@ -272,8 +272,7 @@ IFACEMETHODIMP ZoneWindow::MoveSizeEnd(HWND window, POINT const& ptScreen) noexc
MapWindowPoints(nullptr, m_window.get(), &ptClient, 1); MapWindowPoints(nullptr, m_window.get(), &ptClient, 1);
m_activeZoneSet->MoveWindowIntoZoneByIndexSet(window, m_window.get(), m_highlightZone); m_activeZoneSet->MoveWindowIntoZoneByIndexSet(window, m_window.get(), m_highlightZone);
auto windowInfo = FancyZonesUtils::GetFancyZonesWindowInfo(window); if (FancyZonesUtils::HasNoVisibleOwner(window))
if (windowInfo.noVisibleOwner)
{ {
SaveWindowProcessToZoneIndex(window); SaveWindowProcessToZoneIndex(window);
} }
@ -307,8 +306,7 @@ ZoneWindow::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, boo
{ {
if (m_activeZoneSet->MoveWindowIntoZoneByDirectionAndIndex(window, m_window.get(), vkCode, cycle)) if (m_activeZoneSet->MoveWindowIntoZoneByDirectionAndIndex(window, m_window.get(), vkCode, cycle))
{ {
auto windowInfo = FancyZonesUtils::GetFancyZonesWindowInfo(window); if (FancyZonesUtils::HasNoVisibleOwner(window))
if (windowInfo.noVisibleOwner)
{ {
SaveWindowProcessToZoneIndex(window); SaveWindowProcessToZoneIndex(window);
} }

View file

@ -18,26 +18,6 @@ namespace NonLocalizable
namespace namespace
{ {
bool HasNoVisibleOwner(HWND window) noexcept
{
auto owner = GetWindow(window, GW_OWNER);
if (owner == nullptr)
{
return true; // There is no owner at all
}
if (!IsWindowVisible(owner))
{
return true; // Owner is invisible
}
RECT rect;
if (!GetWindowRect(owner, &rect))
{
return false; // Could not get the rect, return true (and filter out the window) just in case
}
// It is enough that the window is zero-sized in one dimension only.
return rect.top == rect.bottom || rect.left == rect.right;
}
bool IsZonableByProcessPath(const std::wstring& processPath, const std::vector<std::wstring>& excludedApps) bool IsZonableByProcessPath(const std::wstring& processPath, const std::vector<std::wstring>& excludedApps)
{ {
// Filter out user specified apps // Filter out user specified apps
@ -201,12 +181,31 @@ namespace FancyZonesUtils
::SetWindowPlacement(window, &placement); ::SetWindowPlacement(window, &placement);
} }
FancyZonesWindowInfo GetFancyZonesWindowInfo(HWND window) bool HasNoVisibleOwner(HWND window) noexcept
{
auto owner = GetWindow(window, GW_OWNER);
if (owner == nullptr)
{
return true; // There is no owner at all
}
if (!IsWindowVisible(owner))
{
return true; // Owner is invisible
}
RECT rect;
if (!GetWindowRect(owner, &rect))
{
return false; // Could not get the rect, return true (and filter out the window) just in case
}
// It is enough that the window is zero-sized in one dimension only.
return rect.top == rect.bottom || rect.left == rect.right;
}
bool IsStandardWindow(HWND window)
{ {
FancyZonesWindowInfo result;
if (GetAncestor(window, GA_ROOT) != window || !IsWindowVisible(window)) if (GetAncestor(window, GA_ROOT) != window || !IsWindowVisible(window))
{ {
return result; return false;
} }
auto style = GetWindowLong(window, GWL_STYLE); auto style = GetWindowLong(window, GWL_STYLE);
auto exStyle = GetWindowLong(window, GWL_EXSTYLE); auto exStyle = GetWindowLong(window, GWL_EXSTYLE);
@ -217,56 +216,51 @@ namespace FancyZonesUtils
(style & WS_MINIMIZEBOX) == 0 && (style & WS_MINIMIZEBOX) == 0 &&
(style & WS_MAXIMIZEBOX) == 0) (style & WS_MAXIMIZEBOX) == 0)
{ {
return result; return false;
} }
if ((style & WS_CHILD) == WS_CHILD || if ((style & WS_CHILD) == WS_CHILD ||
(style & WS_DISABLED) == WS_DISABLED || (style & WS_DISABLED) == WS_DISABLED ||
(exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW || (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW ||
(exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE) (exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE)
{ {
return result; return false;
} }
std::array<char, 256> class_name; std::array<char, 256> class_name;
GetClassNameA(window, class_name.data(), static_cast<int>(class_name.size())); GetClassNameA(window, class_name.data(), static_cast<int>(class_name.size()));
if (is_system_window(window, class_name.data())) if (is_system_window(window, class_name.data()))
{ {
return result; return false;
} }
auto process_path = get_process_path(window); auto process_path = get_process_path(window);
// Check for Cortana: // Check for Cortana:
if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 && if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 &&
process_path.ends_with(L"SearchUI.exe")) process_path.ends_with(L"SearchUI.exe"))
{ {
return result; return false;
} }
result.processPath = std::move(process_path);
result.standardWindow = true; return true;
result.noVisibleOwner = HasNoVisibleOwner(window);
return result;
} }
bool IsCandidateForLastKnownZone(HWND window, const std::vector<std::wstring>& excludedApps) noexcept bool IsCandidateForLastKnownZone(HWND window, const std::vector<std::wstring>& excludedApps) noexcept
{ {
auto windowInfo = GetFancyZonesWindowInfo(window); auto zonable = IsStandardWindow(window) && HasNoVisibleOwner(window);
auto zonable = windowInfo.standardWindow && windowInfo.noVisibleOwner;
if (!zonable) if (!zonable)
{ {
return false; return false;
} }
return IsZonableByProcessPath(windowInfo.processPath, excludedApps); return IsZonableByProcessPath(get_process_path(window), excludedApps);
} }
bool IsCandidateForZoning(HWND window, const std::vector<std::wstring>& excludedApps) noexcept bool IsCandidateForZoning(HWND window, const std::vector<std::wstring>& excludedApps) noexcept
{ {
auto windowInfo = GetFancyZonesWindowInfo(window); if (!IsStandardWindow(window))
if (!windowInfo.standardWindow)
{ {
return false; return false;
} }
return IsZonableByProcessPath(windowInfo.processPath, excludedApps); return IsZonableByProcessPath(get_process_path(window), excludedApps);
} }
bool IsWindowMaximized(HWND window) noexcept bool IsWindowMaximized(HWND window) noexcept

View file

@ -5,17 +5,6 @@
namespace FancyZonesUtils namespace FancyZonesUtils
{ {
// Window properties relevant to FancyZones
struct FancyZonesWindowInfo
{
// True if from the styles the window looks like a standard window
bool standardWindow = false;
// True if the window is a top-level window that does not have a visible owner
bool noVisibleOwner = false;
// Path to the executable owning the window
std::wstring processPath;
};
struct Rect struct Rect
{ {
Rect() {} Rect() {}
@ -200,7 +189,8 @@ namespace FancyZonesUtils
void OrderMonitors(std::vector<std::pair<HMONITOR, RECT>>& monitorInfo); void OrderMonitors(std::vector<std::pair<HMONITOR, RECT>>& monitorInfo);
void SizeWindowToRect(HWND window, RECT rect) noexcept; void SizeWindowToRect(HWND window, RECT rect) noexcept;
FancyZonesWindowInfo GetFancyZonesWindowInfo(HWND window); bool HasNoVisibleOwner(HWND window) noexcept;
bool IsStandardWindow(HWND window);
bool IsCandidateForLastKnownZone(HWND window, const std::vector<std::wstring>& excludedApps) noexcept; bool IsCandidateForLastKnownZone(HWND window, const std::vector<std::wstring>& excludedApps) noexcept;
bool IsCandidateForZoning(HWND window, const std::vector<std::wstring>& excludedApps) noexcept; bool IsCandidateForZoning(HWND window, const std::vector<std::wstring>& excludedApps) noexcept;