FancyZones: improve windows and apps filtering (#673)

Unifies the way windows are considered "interesting" by FancyZone.
Berfore the change WinKey + arrows would use different method than
dragging. This PR makes both use the WinKey + arrows method.

Cleans up FancyZones Settings.cpp by removing m_configStrings variable.
Contrary to its name it was used to create color picker control.

Adds a multiline option to the text input to settings. Uses this to
provide the user with a way to exclude certain apps from snapping to
zones.
This commit is contained in:
Bartosz Sosnowski
2019-11-18 10:29:56 +01:00
committed by GitHub
parent 4df1d2093f
commit 03438f9192
15 changed files with 537 additions and 332 deletions

View File

@@ -1,5 +1,6 @@
#include "pch.h"
#include "common.h"
#include "hwnd_data_cache.h"
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
#include <strsafe.h>
@@ -32,48 +33,13 @@ std::optional<POINT> get_mouse_pos() {
return point;
}
}
HWND get_filtered_active_window() {
static auto desktop = GetDesktopWindow();
static auto shell = GetShellWindow();
static HWND searchui = nullptr;
auto active_window = GetForegroundWindow();
active_window = GetAncestor(active_window, GA_ROOT);
if (active_window == desktop || active_window == shell || active_window == searchui) {
return nullptr;
}
auto window_styles = GetWindowLong(active_window, GWL_STYLE);
if ((window_styles & WS_CHILD) || (window_styles & WS_DISABLED)) {
return nullptr;
}
window_styles = GetWindowLong(active_window, GWL_EXSTYLE);
if ((window_styles & WS_EX_TOOLWINDOW) ||(window_styles & WS_EX_NOACTIVATE)) {
return nullptr;
}
char class_name[256] = "";
GetClassNameA(active_window, class_name, 256);
if (strcmp(class_name, "SysListView32") == 0 ||
strcmp(class_name, "WorkerW") == 0 ||
strcmp(class_name, "Shell_TrayWnd") == 0 ||
strcmp(class_name, "Shell_SecondaryTrayWnd") == 0 ||
strcmp(class_name, "Progman") == 0) {
return nullptr;
}
if (strcmp(class_name, "Windows.UI.Core.CoreWindow") == 0) {
const static std::wstring cortana_app = L"SearchUI.exe";
auto process_path = get_process_path(active_window);
if (process_path.length() >= cortana_app.length() &&
process_path.compare(process_path.length() - cortana_app.length(), cortana_app.length(), cortana_app) == 0) {
// cache the cortana HWND
searchui = active_window;
return nullptr;
}
}
return active_window;
WindowAndProcPath get_filtered_base_window_and_path(HWND window) {
return hwnd_cache.get_window_and_path(window);
}
HWND get_filtered_active_window() {
return hwnd_cache.get_window(GetForegroundWindow());
}
int width(const RECT& rect) {

View File

@@ -11,6 +11,12 @@ std::optional<RECT> get_window_pos(HWND hwnd);
std::optional<POINT> get_mouse_pos();
// Gets active window, filtering out all "non standard" windows like the taskbar, etc.
HWND get_filtered_active_window();
// Gets window ancestor (usualy the window we want to do stuff with), filtering out all "non standard" windows like the taskbar, etc. and provide the app process path
struct WindowAndProcPath {
HWND hwnd = nullptr;
std::wstring process_path;
};
WindowAndProcPath get_filtered_base_window_and_path(HWND window);
// Calculate sizes
int width(const RECT& rect);

View File

@@ -1,141 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{74485049-C722-400F-ABE5-86AC52D929B3}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>common</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>common</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>inc;telemetry;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>inc;telemetry;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="animation.h" />
<ClInclude Include="async_message_queue.h" />
<ClInclude Include="d2d_svg.h" />
<ClInclude Include="d2d_text.h" />
<ClInclude Include="d2d_window.h" />
<ClInclude Include="dpi_aware.h" />
<ClInclude Include="monitors.h" />
<ClInclude Include="on_thread_executor.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="settings_helpers.h" />
<ClInclude Include="settings_objects.h" />
<ClInclude Include="start_visible.h" />
<ClInclude Include="tasklist_positions.h" />
<ClInclude Include="common.h" />
<ClInclude Include="Telemetry\ProjectTelemetry.h" />
<ClInclude Include="Telemetry\TraceLoggingDefines.h" />
<ClInclude Include="two_way_pipe_message_ipc.h" />
<ClInclude Include="version.h" />
<ClInclude Include="windows_colors.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="animation.cpp" />
<ClCompile Include="d2d_svg.cpp" />
<ClCompile Include="d2d_text.cpp" />
<ClCompile Include="d2d_window.cpp" />
<ClCompile Include="dpi_aware.cpp" />
<ClCompile Include="monitors.cpp" />
<ClCompile Include="on_thread_executor.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="settings_helpers.cpp" />
<ClCompile Include="settings_objects.cpp" />
<ClCompile Include="start_visible.cpp" />
<ClCompile Include="tasklist_positions.cpp" />
<ClCompile Include="common.cpp" />
<ClCompile Include="windows_colors.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\deps\cpprestsdk\cpprestsdk.vcxproj">
<Project>{4e577735-dfab-41af-8a6e-b6e8872a2928}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{74485049-C722-400F-ABE5-86AC52D929B3}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>common</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>common</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>inc;telemetry;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>inc;telemetry;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="animation.h" />
<ClInclude Include="async_message_queue.h" />
<ClInclude Include="d2d_svg.h" />
<ClInclude Include="d2d_text.h" />
<ClInclude Include="d2d_window.h" />
<ClInclude Include="dpi_aware.h" />
<ClInclude Include="hwnd_data_cache.h" />
<ClInclude Include="monitors.h" />
<ClInclude Include="on_thread_executor.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="settings_helpers.h" />
<ClInclude Include="settings_objects.h" />
<ClInclude Include="start_visible.h" />
<ClInclude Include="tasklist_positions.h" />
<ClInclude Include="common.h" />
<ClInclude Include="Telemetry\ProjectTelemetry.h" />
<ClInclude Include="Telemetry\TraceLoggingDefines.h" />
<ClInclude Include="two_way_pipe_message_ipc.h" />
<ClInclude Include="version.h" />
<ClInclude Include="windows_colors.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="animation.cpp" />
<ClCompile Include="d2d_svg.cpp" />
<ClCompile Include="d2d_text.cpp" />
<ClCompile Include="d2d_window.cpp" />
<ClCompile Include="dpi_aware.cpp" />
<ClCompile Include="hwnd_data_cache.cpp" />
<ClCompile Include="monitors.cpp" />
<ClCompile Include="on_thread_executor.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="settings_helpers.cpp" />
<ClCompile Include="settings_objects.cpp" />
<ClCompile Include="start_visible.cpp" />
<ClCompile Include="tasklist_positions.cpp" />
<ClCompile Include="common.cpp" />
<ClCompile Include="windows_colors.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\deps\cpprestsdk\cpprestsdk.vcxproj">
<Project>{4e577735-dfab-41af-8a6e-b6e8872a2928}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -1,118 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Header Files\Direct2D">
<UniqueIdentifier>{ed0f9961-6b12-408b-8dbc-fed779a557ac}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Telemetry">
<UniqueIdentifier>{3e9f944e-5d97-4a28-8865-2eff3a3568e7}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="d2d_svg.h">
<Filter>Header Files\Direct2D</Filter>
</ClInclude>
<ClInclude Include="d2d_text.h">
<Filter>Header Files\Direct2D</Filter>
</ClInclude>
<ClInclude Include="d2d_window.h">
<Filter>Header Files\Direct2D</Filter>
</ClInclude>
<ClInclude Include="pch.h" />
<ClInclude Include="animation.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="monitors.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="tasklist_positions.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="windows_colors.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="start_visible.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Telemetry\ProjectTelemetry.h">
<Filter>Header Files\Telemetry</Filter>
</ClInclude>
<ClInclude Include="Telemetry\TraceLoggingDefines.h">
<Filter>Header Files\Telemetry</Filter>
</ClInclude>
<ClInclude Include="two_way_pipe_message_ipc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="async_message_queue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="settings_helpers.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="settings_objects.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dpi_aware.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="version.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="on_thread_executor.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="d2d_svg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="d2d_text.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="d2d_window.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp" />
<ClCompile Include="animation.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="monitors.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tasklist_positions.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="windows_colors.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="start_visible.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="common.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="settings_helpers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="settings_objects.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dpi_aware.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="on_thread_executor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Header Files\Direct2D">
<UniqueIdentifier>{ed0f9961-6b12-408b-8dbc-fed779a557ac}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Telemetry">
<UniqueIdentifier>{3e9f944e-5d97-4a28-8865-2eff3a3568e7}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="d2d_svg.h">
<Filter>Header Files\Direct2D</Filter>
</ClInclude>
<ClInclude Include="d2d_text.h">
<Filter>Header Files\Direct2D</Filter>
</ClInclude>
<ClInclude Include="d2d_window.h">
<Filter>Header Files\Direct2D</Filter>
</ClInclude>
<ClInclude Include="pch.h" />
<ClInclude Include="animation.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="monitors.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="tasklist_positions.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="windows_colors.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="start_visible.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Telemetry\ProjectTelemetry.h">
<Filter>Header Files\Telemetry</Filter>
</ClInclude>
<ClInclude Include="Telemetry\TraceLoggingDefines.h">
<Filter>Header Files\Telemetry</Filter>
</ClInclude>
<ClInclude Include="two_way_pipe_message_ipc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="async_message_queue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="settings_helpers.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="settings_objects.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dpi_aware.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="version.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="on_thread_executor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hwnd_data_cache.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="d2d_svg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="d2d_text.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="d2d_window.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp" />
<ClCompile Include="animation.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="monitors.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tasklist_positions.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="windows_colors.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="start_visible.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="common.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="settings_helpers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="settings_objects.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dpi_aware.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="on_thread_executor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hwnd_data_cache.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,120 @@
#include "pch.h"
#include "hwnd_data_cache.h"
HWNDDataCache hwnd_cache;
WindowAndProcPath HWNDDataCache::get_window_and_path(HWND hwnd) {
std::unique_lock lock(mutex);
auto ptr = get_internal(hwnd);
return ptr ? *ptr : WindowAndProcPath{};
}
HWND HWNDDataCache::get_window(HWND hwnd) {
std::unique_lock lock(mutex);
auto ptr = get_internal(hwnd);
return ptr ? ptr->hwnd : nullptr;
}
WindowAndProcPath* HWNDDataCache::get_internal(HWND hwnd) {
auto root = GetAncestor(hwnd, GA_ROOT);
// Filter the fast and easy cases
if (is_invalid_hwnd(root) ||
is_invalid_class(root) ||
is_invalid_style(root)) {
return nullptr;
}
// Get the HWND process path from the cache
DWORD pid = GetWindowThreadProcessId(root, nullptr);
auto cache_ptr = get_from_cache(root, pid);
if (cache_ptr == nullptr) {
cache_ptr = put_in_cache(root, pid);
}
// If the app is a UWP app, check if it isnt banned
if (is_uwp_app(root) && is_invalid_uwp_app(cache_ptr->process_path)) {
// cache the HWND of the invalid app so we wont search for it again
invalid_hwnds.push_back(root);
return nullptr;
}
return cache_ptr;
}
WindowAndProcPath* HWNDDataCache::get_from_cache(HWND root, DWORD pid) {
auto next = next_timestamp();
auto it = std::find_if(begin(cache), end(cache), [&](const auto& entry) {
return root == entry.data.hwnd && pid == entry.pid;
});
if (it != end(cache)) {
it->atime = next;
return &(it->data);
}
else {
return nullptr;
}
}
WindowAndProcPath* HWNDDataCache::put_in_cache(HWND root, DWORD pid) {
auto next = next_timestamp();
auto it = std::min_element(begin(cache), end(cache), [](const auto& lhs, const auto& rhs) {
return lhs.atime < rhs.atime;
});
it->atime = next;
it->pid = pid;
it->data.hwnd = root;
it->data.process_path = get_process_path(root);
return &(it->data);
}
bool HWNDDataCache::is_invalid_hwnd(HWND hwnd) const {
return std::find(begin(invalid_hwnds), end(invalid_hwnds), hwnd) != end(invalid_hwnds);
}
bool HWNDDataCache::is_invalid_class(HWND hwnd) const {
std::array<char, 256> class_name;
GetClassNameA(hwnd, class_name.data(), static_cast<int>(class_name.size()));
for (auto invalid : invalid_classes) {
if (strcmp(invalid, class_name.data()) == 0)
return true;
}
return false;
}
bool HWNDDataCache::is_invalid_style(HWND hwnd) const {
auto style = GetWindowLong(hwnd, GWL_STYLE);
for (auto invalid : invalid_basic_styles) {
if ((invalid & style) != 0) {
return true;
}
}
style = GetWindowLong(hwnd, GWL_EXSTYLE);
for (auto invalid : invalid_ext_styles) {
if ((invalid & style) != 0) {
return true;
}
}
return false;
}
bool HWNDDataCache::is_uwp_app(HWND hwnd) const {
std::array<char, 256> class_name;
GetClassNameA(hwnd, class_name.data(), static_cast<int>(class_name.size()));
return strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0;
}
bool HWNDDataCache::is_invalid_uwp_app(const std::wstring& process_path) const {
for (const auto& invalid : invalid_uwp_apps) {
// check if process_path ends in "invalid"
if (process_path.length() >= invalid.length() &&
process_path.compare(process_path.length() - invalid.length(), invalid.length(), invalid) == 0) {
return true;
}
}
return false;
}
unsigned HWNDDataCache::next_timestamp() {
auto next = ++current_timestamp;
if (next == 0) {
// Handle overflow by invalidating the cache
for (auto& entry : cache) {
entry.data.hwnd = nullptr;
}
}
return next;
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include <vector>
#include <string>
#include <Windows.h>
class HWNDDataCache {
public:
WindowAndProcPath get_window_and_path(HWND hwnd);
HWND get_window(HWND hwnd);
private:
// Return pointer to our internal cache - we cannot pass this to user
// since next call to get_* might invalidate that pointer
WindowAndProcPath* get_internal(HWND hwnd);
WindowAndProcPath* get_from_cache(HWND root, DWORD pid);
WindowAndProcPath* put_in_cache(HWND root, DWORD pid);
// Various validation routines
bool is_invalid_hwnd(HWND hwnd) const;
bool is_invalid_class(HWND hwnd) const;
bool is_invalid_style(HWND hwnd) const;
bool is_uwp_app(HWND hwnd) const;
bool is_invalid_uwp_app(const std::wstring& binary_path) const;
// List of HWNDs that are not interesting - like desktop, cortana, etc
std::vector<HWND> invalid_hwnds = { GetDesktopWindow(), GetShellWindow() };
// List of invalid window basic styles
std::vector<LONG> invalid_basic_styles = { WS_CHILD, WS_DISABLED };
// List of invalid window extended styles
std::vector<LONG> invalid_ext_styles = { WS_EX_TOOLWINDOW, WS_EX_NOACTIVATE };
// List of invalid window classes - things like start menu, etc.
std::vector<const char*> invalid_classes = { "SysListView32", "WorkerW", "Shell_TrayWnd", "Shell_SecondaryTrayWnd", "Progman" };
// List of invalid persistent UWP app - like Cortana
std::vector<std::wstring> invalid_uwp_apps = { L"SearchUI.exe" };
// Cache for HWND/PID pair to process path. A collision here, where a new process
// not in cache gets to reuse a cached PID and then reuses the same HWND handle
// seems unlikely.
std::mutex mutex;
// Handle timestamp wrap
unsigned next_timestamp();
unsigned current_timestamp = 0;
struct Entry {
DWORD pid = 0;
// access time - when retiring element from cache we pick
// one with minimal atime value. We update this value
// every time we query the cache
unsigned atime = 0;
WindowAndProcPath data;
};
std::vector<Entry> cache{ 32 };
};
extern HWNDDataCache hwnd_cache;

View File

@@ -80,6 +80,22 @@ namespace PowerToysSettings {
m_json.as_object()[L"properties"].as_object()[name] = item;
}
// add_multiline_string overloads.
void Settings::add_multiline_string(const std::wstring& name, UINT description_resource_id, const std::wstring& value) {
add_multiline_string(name, get_resource(description_resource_id), value);
}
void Settings::add_multiline_string(const std::wstring& name, const std::wstring& description, const std::wstring& value) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"editor_type"] = web::json::value::string(L"string_text");
item.as_object()[L"value"] = web::json::value::string(value);
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
item.as_object()[L"multiline"] = web::json::value::boolean(true);
m_json.as_object()[L"properties"].as_object()[name] = item;
}
// add_color_picker overloads.
void Settings::add_color_picker(const std::wstring& name, UINT description_resource_id, const std::wstring& value) {
add_color_picker(name, get_resource(description_resource_id), value);

View File

@@ -31,6 +31,9 @@ namespace PowerToysSettings {
void add_string(const std::wstring& name, UINT description_resource_id, const std::wstring& value);
void add_string(const std::wstring& name, const std::wstring& description, const std::wstring& value);
void add_multiline_string(const std::wstring& name, UINT description_resource_id, const std::wstring& value);
void add_multiline_string(const std::wstring& name, const std::wstring& description, const std::wstring& value);
void add_color_picker(const std::wstring& name, UINT description_resource_id, const std::wstring& value);
void add_color_picker(const std::wstring& name, const std::wstring& description, const std::wstring& value);

View File

@@ -1,5 +1,6 @@
#include "pch.h"
#include <common/settings_objects.h>
#include <common/common.h>
#include <interface/powertoy_module_interface.h>
#include <interface/lowlevel_keyboard_event_data.h>
#include <interface/win_hook_event_data.h>
@@ -198,11 +199,25 @@ public:
}
private:
static bool IsInterestingWindow(HWND window)
bool IsInterestingWindow(HWND window)
{
auto style = GetWindowLongPtr(window, GWL_STYLE);
auto exStyle = GetWindowLongPtr(window, GWL_EXSTYLE);
return IsWindowVisible(window) && WI_IsFlagSet(style, WS_MAXIMIZEBOX) && WI_IsFlagClear(style, WS_CHILD) && WI_IsFlagClear(exStyle, WS_EX_TOOLWINDOW);
auto windowAndPath = get_filtered_base_window_and_path(window);
if (windowAndPath.hwnd == nullptr)
{
return false;
}
CharUpperBuffW(windowAndPath.process_path.data(), (DWORD)windowAndPath.process_path.length());
if (m_settings)
{
for (const auto& excluded : m_settings->GetSettings().excludedAppsArray)
{
if (windowAndPath.process_path.find(excluded) != std::wstring::npos)
{
return false;
}
}
}
return true;
}
void Disable(bool const traceEvent)

View File

@@ -44,15 +44,9 @@ private:
{ L"use_cursorpos_editor_startupscreen", &m_settings.use_cursorpos_editor_startupscreen, IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN },
};
struct
{
PCWSTR name;
std::wstring* value;
int resourceId;
} m_configStrings[1] = {
{ L"fancyzones_zoneHighlightColor", &m_settings.zoneHightlightColor, IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR },
};
const std::wstring m_editor_hotkey_name = L"fancyzones_editor_hotkey";
const std::wstring m_zoneHiglightName = L"fancyzones_zoneHighlightColor";
const std::wstring m_editorHotkeyName = L"fancyzones_editor_hotkey";
const std::wstring m_excludedAppsName = L"fancyzones_excluded_apps";
};
IFACEMETHODIMP_(bool) FancyZonesSettings::GetConfig(_Out_ PWSTR buffer, _Out_ int *buffer_size) noexcept
@@ -73,17 +67,15 @@ IFACEMETHODIMP_(bool) FancyZonesSettings::GetConfig(_Out_ PWSTR buffer, _Out_ in
IDS_SETTING_LAUNCH_EDITOR_BUTTON,
IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION
);
settings.add_hotkey(m_editor_hotkey_name, IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, m_settings.editorHotkey);
settings.add_hotkey(m_editorHotkeyName, IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, m_settings.editorHotkey);
for (auto const& setting : m_configBools)
{
settings.add_bool_toogle(setting.name, setting.resourceId, *setting.value);
}
for (auto const& setting : m_configStrings)
{
settings.add_color_picker(setting.name, setting.resourceId, *setting.value);
}
settings.add_color_picker(m_zoneHiglightName, IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR, m_settings.zoneHightlightColor);
settings.add_multiline_string(m_excludedAppsName, IDS_SETTING_EXCLCUDED_APPS_DESCRIPTION, m_settings.excludedApps);
return settings.serialize_to_buffer(buffer, buffer_size);
}
@@ -127,17 +119,37 @@ void FancyZonesSettings::LoadSettings(PCWSTR config, bool fromFile) noexcept try
}
}
for (auto const& setting : m_configStrings)
if (values.is_string_value(m_zoneHiglightName))
{
if (values.is_string_value(setting.name))
{
*setting.value = values.get_string_value(setting.name);
}
m_settings.zoneHightlightColor = values.get_string_value(m_zoneHiglightName);
}
if (values.is_object_value(m_editor_hotkey_name))
if (values.is_object_value(m_editorHotkeyName))
{
m_settings.editorHotkey = PowerToysSettings::HotkeyObject::from_json(values.get_json(m_editor_hotkey_name));
m_settings.editorHotkey = PowerToysSettings::HotkeyObject::from_json(values.get_json(m_editorHotkeyName));
}
if (values.is_string_value(m_excludedAppsName))
{
m_settings.excludedApps = values.get_string_value(m_excludedAppsName);
m_settings.excludedAppsArray.clear();
auto excludedUppercase = m_settings.excludedApps;
CharUpperBuffW(excludedUppercase.data(), (DWORD)excludedUppercase.length());
std::wstring_view view(excludedUppercase);
while (view.starts_with('\n') || view.starts_with('\r'))
{
view.remove_prefix(1);
}
while (!view.empty())
{
auto pos = (std::min)(view.find_first_of(L"\r\n"), view.length());
m_settings.excludedAppsArray.emplace_back(view.substr(0, pos));
view.remove_prefix(pos);
while (view.starts_with('\n') || view.starts_with('\r'))
{
view.remove_prefix(1);
}
}
}
}
CATCH_LOG();
@@ -151,12 +163,9 @@ void FancyZonesSettings::SaveSettings() noexcept try
values.add_property(setting.name, *setting.value);
}
for (auto const& setting : m_configStrings)
{
values.add_property(setting.name, *setting.value);
}
values.add_property(m_editor_hotkey_name, m_settings.editorHotkey);
values.add_property(m_zoneHiglightName, m_settings.zoneHightlightColor);
values.add_property(m_editorHotkeyName, m_settings.editorHotkey);
values.add_property(m_excludedAppsName, m_settings.excludedApps);
values.save_to_settings_file();
}

View File

@@ -17,6 +17,8 @@ struct Settings
bool use_cursorpos_editor_startupscreen = true;
std::wstring zoneHightlightColor = L"#0078D7";
PowerToysSettings::HotkeyObject editorHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, false, VK_OEM_3, L"~");
std::wstring excludedApps = L"";
std::vector<std::wstring> excludedAppsArray;
};
interface __declspec(uuid("{BA4E77C4-6F44-4C5D-93D3-CBDE880495C2}")) IFancyZonesSettings : public IUnknown

View File

@@ -13,3 +13,4 @@
#define IDS_SETTING_LAUNCH_EDITOR_BUTTON 113
#define IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION 114
#define IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL 115
#define IDS_SETTING_EXCLCUDED_APPS_DESCRIPTION 116

View File

@@ -9,7 +9,8 @@ export class StringTextSettingsControl extends BaseSettingsControl {
super(props);
this.textref = null;
this.state={
property_values: props.setting
property_values: props.setting,
multiline: !!props.setting.multiline
}
}
@@ -28,6 +29,10 @@ export class StringTextSettingsControl extends BaseSettingsControl {
// Renders a UI Fabric TextField.
return (
<TextField
styles={{ fieldGroup: {
width: '350px',
alignSelf: 'start'
}}}
onChange = {
(_event,_new_value) => {
// Updates the state with the new value introduced in the TextField.
@@ -42,6 +47,7 @@ export class StringTextSettingsControl extends BaseSettingsControl {
this.parent_on_change();
}
}
multiline={this.state.multiline}
value={this.state.property_values.value}
label={this.state.property_values.display_name}
componentRef= {(input) => {this.textref=input;}}

File diff suppressed because one or more lines are too long