mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
[FancyZones] Fix handling newly created windows on Windows 11 (#28646)
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include <FancyZonesLib/Settings.h>
|
||||
#include <FancyZonesLib/SettingsObserver.h>
|
||||
#include <FancyZonesLib/trace.h>
|
||||
#include <FancyZonesLib/VirtualDesktop.h>
|
||||
#include <FancyZonesLib/WindowKeyboardSnap.h>
|
||||
#include <FancyZonesLib/WindowMouseSnap.h>
|
||||
#include <FancyZonesLib/WorkArea.h>
|
||||
@@ -397,12 +398,6 @@ void FancyZones::WindowCreated(HWND window) noexcept
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isCandidateForLastKnownZone = FancyZonesWindowUtils::IsCandidateForZoning(window);
|
||||
if (!isCandidateForLastKnownZone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HMONITOR primary = MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY);
|
||||
HMONITOR active = primary;
|
||||
|
||||
@@ -994,7 +989,7 @@ bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FancyZonesSettings::settings().overrideSnapHotkeys && FancyZonesWindowUtils::IsCandidateForZoning(window))
|
||||
if (FancyZonesSettings::settings().overrideSnapHotkeys)
|
||||
{
|
||||
HMONITOR monitor = WorkAreaKeyFromWindow(window);
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
<ClCompile Include="FancyZonesData\LayoutTemplates.cpp">
|
||||
<PrecompiledHeaderFile>../pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesWindowProcessing.cpp" />
|
||||
<ClCompile Include="FancyZonesWindowProperties.cpp" />
|
||||
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
|
||||
<ClCompile Include="FancyZonesData.cpp" />
|
||||
|
||||
@@ -272,6 +272,9 @@
|
||||
<ClCompile Include="WindowKeyboardSnap.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesWindowProcessing.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#include "pch.h"
|
||||
#include "FancyZonesWindowProcessing.h"
|
||||
|
||||
#include <FancyZonesLib/Settings.h>
|
||||
#include <FancyZonesLib/VirtualDesktop.h>
|
||||
#include <FancyZonesLib/WindowUtils.h>
|
||||
|
||||
bool FancyZonesWindowProcessing::IsProcessable(HWND window) noexcept
|
||||
{
|
||||
const bool isSplashScreen = FancyZonesWindowUtils::IsSplashScreen(window);
|
||||
if (isSplashScreen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool windowMinimized = IsIconic(window);
|
||||
if (windowMinimized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool standard = FancyZonesWindowUtils::IsStandardWindow(window);
|
||||
if (!standard)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// popup could be the window we don't want to snap: start menu, notification popup, tray window, etc.
|
||||
// also, popup could be the windows we want to snap disregarding the "allowSnapPopupWindows" setting, e.g. Telegram
|
||||
bool isPopup = FancyZonesWindowUtils::IsPopupWindow(window) && !FancyZonesWindowUtils::HasThickFrameAndMinimizeMaximizeButtons(window);
|
||||
if (isPopup && !FancyZonesSettings::settings().allowSnapPopupWindows)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// allow child windows
|
||||
auto hasOwner = FancyZonesWindowUtils::HasVisibleOwner(window);
|
||||
if (hasOwner && !FancyZonesSettings::settings().allowSnapChildWindows)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FancyZonesWindowUtils::IsExcluded(window))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (!VirtualDesktop::instance().IsWindowOnCurrentDesktop(window))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,39 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <FancyZonesLib/VirtualDesktop.h>
|
||||
#include <FancyZonesLib/WindowUtils.h>
|
||||
|
||||
namespace FancyZonesWindowProcessing
|
||||
{
|
||||
inline bool IsProcessable(HWND window) noexcept
|
||||
{
|
||||
const bool isSplashScreen = FancyZonesWindowUtils::IsSplashScreen(window);
|
||||
if (isSplashScreen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool windowMinimized = IsIconic(window);
|
||||
if (windowMinimized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// For windows that FancyZones shouldn't process (start menu, tray, popup menus)
|
||||
// VirtualDesktopManager is unable to retrieve virtual desktop id and returns an error.
|
||||
auto desktopId = VirtualDesktop::instance().GetDesktopId(window);
|
||||
if (!desktopId.has_value())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (!VirtualDesktop::instance().IsWindowOnCurrentDesktop(window))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool IsProcessable(HWND window) noexcept;
|
||||
}
|
||||
@@ -32,7 +32,6 @@ WindowMouseSnap::~WindowMouseSnap()
|
||||
std::unique_ptr<WindowMouseSnap> WindowMouseSnap::Create(HWND window, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& activeWorkAreas)
|
||||
{
|
||||
if (!FancyZonesWindowProcessing::IsProcessable(window) ||
|
||||
!FancyZonesWindowUtils::IsCandidateForZoning(window) ||
|
||||
FancyZonesWindowUtils::IsCursorTypeIndicatingSizeEvent())
|
||||
{
|
||||
return nullptr;
|
||||
|
||||
@@ -166,6 +166,8 @@ bool FancyZonesWindowUtils::HasVisibleOwner(HWND window) noexcept
|
||||
|
||||
bool FancyZonesWindowUtils::IsStandardWindow(HWND window)
|
||||
{
|
||||
// True if from the styles the window looks like a standard window
|
||||
|
||||
if (GetAncestor(window, GA_ROOT) != window)
|
||||
{
|
||||
return false;
|
||||
@@ -181,13 +183,6 @@ bool FancyZonesWindowUtils::IsStandardWindow(HWND window)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::array<char, 256> class_name;
|
||||
GetClassNameA(window, class_name.data(), static_cast<int>(class_name.size()));
|
||||
if (is_system_window(window, class_name.data()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -203,44 +198,6 @@ bool FancyZonesWindowUtils::HasThickFrameAndMinimizeMaximizeButtons(HWND window)
|
||||
return ((style & WS_THICKFRAME) == WS_THICKFRAME && (style & WS_MINIMIZEBOX) == WS_MINIMIZEBOX && (style & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX);
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsCandidateForZoning(HWND window)
|
||||
{
|
||||
bool isStandard = IsStandardWindow(window);
|
||||
if (!isStandard)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// popup could be the window we don't want to snap: start menu, notification popup, tray window, etc.
|
||||
// also, popup could be the windows we want to snap disregarding the "allowSnapPopupWindows" setting, e.g. Telegram
|
||||
bool isPopup = IsPopupWindow(window);
|
||||
if (isPopup && !HasThickFrameAndMinimizeMaximizeButtons(window) && !FancyZonesSettings::settings().allowSnapPopupWindows)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// allow child windows
|
||||
auto hasOwner = HasVisibleOwner(window);
|
||||
if (hasOwner && !FancyZonesSettings::settings().allowSnapChildWindows)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring processPath = get_process_path_waiting_uwp(window);
|
||||
CharUpperBuffW(const_cast<std::wstring&>(processPath).data(), static_cast<DWORD>(processPath.length()));
|
||||
if (IsExcludedByUser(window, processPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsExcludedByDefault(window, processPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsProcessOfWindowElevated(HWND window)
|
||||
{
|
||||
DWORD pid = 0;
|
||||
@@ -268,6 +225,23 @@ bool FancyZonesWindowUtils::IsProcessOfWindowElevated(HWND window)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsExcluded(HWND window)
|
||||
{
|
||||
std::wstring processPath = get_process_path_waiting_uwp(window);
|
||||
CharUpperBuffW(const_cast<std::wstring&>(processPath).data(), static_cast<DWORD>(processPath.length()));
|
||||
if (IsExcludedByUser(window, processPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsExcludedByDefault(window, processPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsExcludedByUser(const HWND& hwnd, std::wstring& processPath) noexcept
|
||||
{
|
||||
return (check_excluded_app(hwnd, processPath, FancyZonesSettings::settings().excludedAppsArray));
|
||||
@@ -281,6 +255,13 @@ bool FancyZonesWindowUtils::IsExcludedByDefault(const HWND& hwnd, std::wstring&
|
||||
return true;
|
||||
}
|
||||
|
||||
std::array<char, 256> class_name;
|
||||
GetClassNameA(hwnd, class_name.data(), static_cast<int>(class_name.size()));
|
||||
if (is_system_window(hwnd, class_name.data()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::vector<std::wstring> defaultExcludedApps = { NonLocalizable::PowerToysAppFZEditor, NonLocalizable::CoreWindow, NonLocalizable::SearchUI };
|
||||
return (check_excluded_app(hwnd, processPath, defaultExcludedApps));
|
||||
}
|
||||
|
||||
@@ -21,8 +21,9 @@ namespace FancyZonesWindowUtils
|
||||
bool IsStandardWindow(HWND window);
|
||||
bool IsPopupWindow(HWND window) noexcept;
|
||||
bool HasThickFrameAndMinimizeMaximizeButtons(HWND window) noexcept;
|
||||
bool IsCandidateForZoning(HWND window);
|
||||
bool IsProcessOfWindowElevated(HWND window); // If HWND is already dead, we assume it wasn't elevated
|
||||
|
||||
bool IsExcluded(HWND window);
|
||||
bool IsExcludedByUser(const HWND& hwnd, std::wstring& processPath) noexcept;
|
||||
bool IsExcludedByDefault(const HWND& hwnd, std::wstring& processPath) noexcept;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user