diff --git a/LICENSE b/LICENSE index c35638412f..b2d78c9e34 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -The MIT License (MIT) +The MIT License Copyright (c) Microsoft Corporation. All rights reserved. diff --git a/NOTICE.md b/NOTICE.md index ee6bf9c456..af4cf72190 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1,22 +1,5 @@ # NOTICES AND INFORMATION -Do Not Translate or Localize - -This software incorporates material from third parties. Microsoft makes certain -open source code available at http://3rdpartysource.microsoft.com, or you may -send a check or money order for US $5.00, including the product name, the open -source component name, and version number, to: - -``` -Source Code Compliance Team -Microsoft Corporation -One Microsoft Way -Redmond, WA 98052 -USA -``` - -Notwithstanding any other terms, you may reverse engineer this software to the -extent required to debug changes to any libraries licensed under the GNU Lesser -General Public License. +This software incorporates material from third parties. ## PowerToy: ImageResizer diff --git a/README.md b/README.md index 496c2fd730..7f9aa1b48f 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,12 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline [![Build Status](https://dev.azure.com/ms/PowerToys/_apis/build/status/microsoft.PowerToys?branchName=master)](https://dev.azure.com/ms/PowerToys/_build?definitionId=219) -## Installing and running Microsoft PowerToys 0.16 +## Installing and running Microsoft PowerToys 0.17 👉 **Note:** Microsoft PowerToys requires Windows 10 1803 (build 17134) or later. ### Via Github with MSI [Recommended] -Install from the [Microsoft PowerToys GitHub releases page][github-release-link]. Click on `Assets` to show the files available in the release and then click on `PowerToysSetup-0.16.1-x64.msi` to download the PowerToys installer. +Install from the [Microsoft PowerToys GitHub releases page][github-release-link]. Click on `Assets` to show the files available in the release and then click on `PowerToysSetup-0.17.0-x64.msi` to download the PowerToys installer. This is our preferred method. @@ -90,36 +90,27 @@ Our plan for all the [goals and utilities for v1.0 detailed over here in the wik ## What's Happening -### March 2020 Update +### April 2020 Update -Our mantra for the 0.16 was adding in new features along with a continual push for quality and stability. We are working toward getting a way to auto-update PowerToys and have a good plan for this. We want to proactively thank the community for quickly identifying a few bugs inside 0.15 and allowing us to quickly release 0.15.1 and 0.15.2. +Our goals for 0.17 release cycle were updatability and stability. -Below are just a few of the bullet items from this release. +**Auto-updating:** We just added in the code for doing updating, so the first chance to experience this will be when 0.18 is released. We’re also seeing how aggressive everyone wants with this so right now, you’ll have to click “Install” for it to kick off the installer. This is something we’d love feedback on. -- We shipped [v0.16][github-release-link]! -- FancyZone improvement: - - Multi-Monitor improvement: Zone flipping switching now works between monitors! - - Simplified UX: Removed layout hot-swap and flashing feature due to need to improve multi-monitor support -- New Utilities! - - Markdown Preview pane extension - - SVG Preview pane extension - - Image Resizer Window Shell extension - - Window Walker, an alt-tab alternative -- Fixed over 100 issues! -- Testing improvements - - 54 UX Functional tests - - 161 new Unit tests - -For [0.17](https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F3), we are proactively working on: +Another thing we did was utilized telemetry from PowerToys to prioritize virtual desktop FancyZone work. We knew there was a subset of bugs caused by an underlying issue and seeing how many users it affected helped us reprioritize to do the work sooner. +- We shipped [v0.17][github-release-link]! - Auto-updating +- FancyZone improvement: + - Virtual desktop support should be much better! + - Better taskbar positioning +- Fixed non-admin install regression. +- Lots of bug fixes! + +For [0.18](https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F4), we are proactively working on: - Win+R replacement (Launcher) - Keyboard remapping - Performance improvements with FancyZones - A testing utility for FancyZones to be sure we can test different window configurations. - -Future release work, we are proactively working on: - - Settings v2 / Fix bug #243 ## Developer Guidance diff --git a/doc/planning/FancyZonesBacklog.md b/doc/planning/FancyZonesBacklog.md index 459f644869..a94b41ca40 100644 --- a/doc/planning/FancyZonesBacklog.md +++ b/doc/planning/FancyZonesBacklog.md @@ -3,25 +3,17 @@ This file captures the prioritized list of issues the FancyZones team will tackle ## On deck -Implement multi-mon editor support [195](https://github.com/microsoft/PowerToys/issues/195) -Add telemetry to new editor [196](https://github.com/microsoft/PowerToys/issues/196) ## Backlog Add tests to the new editor [197](https://github.com/microsoft/PowerToys/issues/197) -Hitting Esc while dragging should cancel the drag and not move the window into a zone [170](https://github.com/microsoft/PowerToys/issues/170) -Flash Zones is wayyyy too slow with multiple large monitors [167](https://github.com/microsoft/PowerToys/issues/167) Cycle through windows in a Zone [175](https://github.com/microsoft/PowerToys/issues/175) Minimize/restore windows in a zone as a group [174](https://github.com/microsoft/PowerToys/issues/174) FancyZones should support custom layouts for different "environments" [177](https://github.com/microsoft/PowerToys/issues/177) -Win+arrow works between monitors [161](https://github.com/microsoft/PowerToys/issues/161) Win+arrow is directional based on zone rect [162](https://github.com/microsoft/PowerToys/issues/162) Dragging a zoned window should restore size to a checkpointed size instead of current rect [166](https://github.com/microsoft/PowerToys/issues/166) FancyZones should merge with MTND and include zone moves in the pop-up [178](https://github.com/microsoft/PowerToys/issues/178) Drag to edge of screen automatically switches virtual desktops [168](https://github.com/microsoft/PowerToys/issues/168) -Different color schemes [165](https://github.com/microsoft/PowerToys/issues/165) -Ensure you can easily see zone while dragging [163](https://github.com/microsoft/PowerToys/issues/163) Visual updates for Win+Arrow [171](https://github.com/microsoft/PowerToys/issues/171) -Add a CLI for FancyZones [180](https://github.com/microsoft/PowerToys/issues/180) Add "magnetic dragging and resizing" mode to FancyZones [181](https://github.com/microsoft/PowerToys/issues/181) Create layout from current windows [159](https://github.com/microsoft/PowerToys/issues/159) Zone sets that have a dynamic number of zones [160](https://github.com/microsoft/PowerToys/issues/160) diff --git a/installer/Version.props b/installer/Version.props index 880a9ef2d9..a469b0f307 100644 --- a/installer/Version.props +++ b/installer/Version.props @@ -1,7 +1,7 @@ - 0.17.0 + 0.17.1 Version=$(Version); \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000000..9eaf83e309 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,14 @@ + + + + <_PropertySheetDisplayName>PowerToys.Root.Props + + + + + false + pch.h + stdcpplatest + + + \ No newline at end of file diff --git a/src/action_runner/action_runner.vcxproj b/src/action_runner/action_runner.vcxproj index 06f5f44e6a..8543460329 100644 --- a/src/action_runner/action_runner.vcxproj +++ b/src/action_runner/action_runner.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -22,7 +23,7 @@ 16.0 {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D} actionrunner - 10.0 + 10.0.17134.0 action_runner @@ -93,7 +94,6 @@ true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true stdcpplatest true MultiThreaded @@ -111,7 +111,6 @@ Level3 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true Console @@ -123,7 +122,6 @@ Level4 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true stdcpplatest true MultiThreadedDebug @@ -141,7 +139,6 @@ true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true Console @@ -164,7 +161,18 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/action_runner/packages.config b/src/action_runner/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/action_runner/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj b/src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj index 9667cf1f52..5cca53553a 100644 --- a/src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj +++ b/src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {1A066C63-64B3-45F8-92FE-664E1CCE8077} Win32Proj UnitTestsCommonLib - 10.0 + 10.0.17134.0 NativeUnitTestProject @@ -113,7 +114,18 @@ {74485049-c722-400f-abe5-86ac52d929b3} + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj.filters b/src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj.filters index 07ce02df23..d130140a5e 100644 --- a/src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj.filters +++ b/src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj.filters @@ -33,4 +33,7 @@ Header Files + + + \ No newline at end of file diff --git a/src/common/UnitTests-CommonLib/packages.config b/src/common/UnitTests-CommonLib/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/common/UnitTests-CommonLib/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/common/UnitTests-CommonLib/pch.h b/src/common/UnitTests-CommonLib/pch.h index d7c448a6ed..a3983204aa 100644 --- a/src/common/UnitTests-CommonLib/pch.h +++ b/src/common/UnitTests-CommonLib/pch.h @@ -9,8 +9,9 @@ // add headers that you want to pre-compile here #include -#include - +#include +#include +#include #include "CppUnitTest.h" #endif //PCH_H diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 1bcaae0e70..7ab6c2b0a1 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -1,5 +1,6 @@ + @@ -25,7 +26,7 @@ {74485049-C722-400F-ABE5-86AC52D929B3} Win32Proj common - 10.0 + 10.0.17134.0 common @@ -70,7 +71,6 @@ Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) - true pch.h stdcpplatest MultiThreadedDebug @@ -94,7 +94,6 @@ true true NDEBUG;_LIB;%(PreprocessorDefinitions) - true stdcpplatest pch.h MultiThreaded @@ -178,11 +177,14 @@ + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + \ No newline at end of file diff --git a/src/common/json.h b/src/common/json.h index 141cc107a4..c0ec8eb14c 100644 --- a/src/common/json.h +++ b/src/common/json.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include diff --git a/src/common/notifications/notifications_dll.vcxproj b/src/common/notifications/notifications_dll.vcxproj index dc7b54cc16..a5b2f8e718 100644 --- a/src/common/notifications/notifications_dll.vcxproj +++ b/src/common/notifications/notifications_dll.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -23,7 +24,7 @@ {031AC72E-FA28-4AB7-B690-6F7B9C28AA73} Win32Proj notificationsdll - 10.0 + 10.0.17134.0 @@ -96,7 +97,6 @@ true true NDEBUG;NOTIFICATIONSDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h stdcpplatest /await %(AdditionalOptions) @@ -119,7 +119,6 @@ Level3 true WIN32;_DEBUG;NOTIFICATIONSDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h @@ -134,7 +133,6 @@ Level4 true _DEBUG;NOTIFICATIONSDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h stdcpplatest /await %(AdditionalOptions) @@ -157,7 +155,6 @@ true true WIN32;NDEBUG;NOTIFICATIONSDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h @@ -171,6 +168,7 @@ + @@ -187,10 +185,18 @@ + {031AC72E-FA28-4AB7-B690-6F7B9C28AA73} + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/common/notifications/notifications_dll.vcxproj.filters b/src/common/notifications/notifications_dll.vcxproj.filters index daaa21a60d..961fcce8be 100644 --- a/src/common/notifications/notifications_dll.vcxproj.filters +++ b/src/common/notifications/notifications_dll.vcxproj.filters @@ -19,6 +19,7 @@ Resource Files + diff --git a/src/common/notifications/packages.config b/src/common/notifications/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/common/notifications/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/common/notifications_winrt/PropertySheet.props b/src/common/notifications_winrt/PropertySheet.props deleted file mode 100644 index e34141b019..0000000000 --- a/src/common/notifications_winrt/PropertySheet.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/common/notifications_winrt/notifications.vcxproj b/src/common/notifications_winrt/notifications.vcxproj index d44d6c9e1d..95d699b4a6 100644 --- a/src/common/notifications_winrt/notifications.vcxproj +++ b/src/common/notifications_winrt/notifications.vcxproj @@ -14,7 +14,7 @@ true Windows Store 10.0 - 10.0 + 10.0.17134.0 10.0.17134.0 @@ -69,9 +69,6 @@ - - - notifications @@ -105,7 +102,6 @@ _DEBUG;%(PreprocessorDefinitions) true - true stdcpplatest @@ -113,7 +109,6 @@ NDEBUG;%(PreprocessorDefinitions) true - true stdcpplatest diff --git a/src/common/packages.config b/src/common/packages.config index 4f733475e9..0e9399589b 100644 --- a/src/common/packages.config +++ b/src/common/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/src/common/pch.h b/src/common/pch.h index 68a805c03a..8b9652ae35 100644 --- a/src/common/pch.h +++ b/src/common/pch.h @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/src/common/updating/updating.cpp b/src/common/updating/updating.cpp index c102f193a3..d10ba7e912 100644 --- a/src/common/updating/updating.cpp +++ b/src/common/updating/updating.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/src/common/updating/updating.vcxproj b/src/common/updating/updating.vcxproj index 220d5d363b..24f332d921 100644 --- a/src/common/updating/updating.vcxproj +++ b/src/common/updating/updating.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -23,7 +24,7 @@ {17DA04DF-E393-4397-9CF0-84DABE11032E} Win32Proj updating - 10.0 + 10.0.17134.0 updating @@ -95,7 +96,6 @@ true true NDEBUG;_LIB;%(PreprocessorDefinitions) - true pch.h stdcpplatest true @@ -120,7 +120,6 @@ Level3 true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true pch.h ../;%(AdditionalIncludeDirectories) @@ -135,7 +134,6 @@ Level3 true _DEBUG;_LIB;%(PreprocessorDefinitions) - true pch.h stdcpplatest true @@ -160,7 +158,6 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true pch.h ../;%(AdditionalIncludeDirectories) @@ -189,7 +186,18 @@ {74485049-c722-400f-abe5-86ac52d929b3} + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/common/updating/updating.vcxproj.filters b/src/common/updating/updating.vcxproj.filters index c708d3e9f6..6523291f59 100644 --- a/src/common/updating/updating.vcxproj.filters +++ b/src/common/updating/updating.vcxproj.filters @@ -30,4 +30,7 @@ Source Files + + + \ No newline at end of file diff --git a/src/modules/example_powertoy/example_powertoy.vcxproj b/src/modules/example_powertoy/example_powertoy.vcxproj index 786347819a..78506a8057 100644 --- a/src/modules/example_powertoy/example_powertoy.vcxproj +++ b/src/modules/example_powertoy/example_powertoy.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {44CC9375-3E6E-4D99-8913-7FB748807EBD} Win32Proj examplepowertoy - 10.0 + 10.0.17134.0 @@ -60,7 +61,6 @@ Disabled true _DEBUG;EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h ..\..\common\inc;..\..\common\Telemetry;..\;..\..\;..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) MultiThreadedDebug @@ -81,7 +81,6 @@ true true NDEBUG;EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h ..\..\common\inc;..\..\common\Telemetry;..\;..\..\;..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) MultiThreaded @@ -118,7 +117,18 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/example_powertoy/example_powertoy.vcxproj.filters b/src/modules/example_powertoy/example_powertoy.vcxproj.filters index 11a00156ce..e69fd9068f 100644 --- a/src/modules/example_powertoy/example_powertoy.vcxproj.filters +++ b/src/modules/example_powertoy/example_powertoy.vcxproj.filters @@ -13,4 +13,7 @@ + + + \ No newline at end of file diff --git a/src/modules/example_powertoy/packages.config b/src/modules/example_powertoy/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/example_powertoy/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/example_powertoy/pch.h b/src/modules/example_powertoy/pch.h index bf883a660a..fe34ebab4b 100644 --- a/src/modules/example_powertoy/pch.h +++ b/src/modules/example_powertoy/pch.h @@ -1,4 +1,6 @@ #pragma once #define WIN32_LEAN_AND_MEAN #include +#include +#include #include \ No newline at end of file diff --git a/src/modules/fancyzones/FancyZones.png b/src/modules/fancyzones/FancyZones.png index 107c1749f5..73d0cb0fd1 100644 Binary files a/src/modules/fancyzones/FancyZones.png and b/src/modules/fancyzones/FancyZones.png differ diff --git a/src/modules/fancyzones/FancyZonesSettings.png b/src/modules/fancyzones/FancyZonesSettings.png deleted file mode 100644 index edbe76a8c4..0000000000 Binary files a/src/modules/fancyzones/FancyZonesSettings.png and /dev/null differ diff --git a/src/modules/fancyzones/FancyZonesSettings1.png b/src/modules/fancyzones/FancyZonesSettings1.png new file mode 100644 index 0000000000..005fde70d6 Binary files /dev/null and b/src/modules/fancyzones/FancyZonesSettings1.png differ diff --git a/src/modules/fancyzones/FancyZonesSettings2.png b/src/modules/fancyzones/FancyZonesSettings2.png new file mode 100644 index 0000000000..13b8c388aa Binary files /dev/null and b/src/modules/fancyzones/FancyZonesSettings2.png differ diff --git a/src/modules/fancyzones/README.md b/src/modules/fancyzones/README.md index 8eacbd3924..9789948939 100644 --- a/src/modules/fancyzones/README.md +++ b/src/modules/fancyzones/README.md @@ -1,43 +1,64 @@ # Overview -Fancy Zones is a window manager that is designed to make it easy to arrange and snap windows into efficient layouts for your workflow and also to restore these layouts quickly. Fancy Zones allows the user to define a set of window locations for a desktop that are drag targets for windows. When the user drags a window into a zone, the windows is resized and repositioned to fill that zone. +FancyZones is a window manager that is designed to make it easy to arrange and snap windows into efficient layouts for your workflow and also to restore these layouts quickly. FancyZones allows the user to define a set of window locations for a desktop that are drag targets for windows. When the user drags a window into a zone, the window is resized and repositioned to fill that zone. -![Fancy Zones](FancyZones.png) +![FancyZones](FancyZones.png) -To get started with Fancy Zones, you need to enable the utility in Power Toys settings and then invoke the Fancy Zones setup UI. There is a button in settings to invoke this UI, or you can press Win+` (note that this shortcut can be changed in the settings dialog) to launch it. When first launched, the UI presents a list of zone layouts that can be quickly adjusted by how many windows are on the monitor. Choosing a layout shows a preview of that layout on the monitor. Pressing the save and close button sets that layout to the monitor. +To get started with FancyZones, you need to enable the utility in PowerToys settings and then invoke the FancyZones editor UI. +There is a button in settings to invoke the editor, or you can press Win+` (note that this shortcut can be changed in the settings dialog) to launch it. +If you have multiple monitors, to edit the zone settings on each monitor, move the mouse to the desired monitor and then press Win+` to launch the editor UI for that monitor, or move the PowerToys settings window to the desired monitor and then launch the editor UI using the `Edit zones` button. -![Fancy Zones Picker](Picker.png) +When first launched, the UI presents a list of zone layouts that can be quickly adjusted by how many windows are on the monitor. Choosing a layout shows a preview of that layout on the monitor. Pressing the save and close button sets that layout to the monitor. -The editor also supports creating and saving custom layouts. This functionality is in the “Custom” tab in the editor UI. There are two ways to create custom zone layouts, window layout and table layout. These can also be thought of as additive and subtractive models. The additive window layout model starts with a blank layout and supports adding zones that can be dragged and resized similar to windows. +![FancyZones Picker](Picker.png) -![Fancy Zones Window Editor Mode](WindowEditor.png) +The editor also supports creating and saving custom layouts. This functionality is in the `Custom` tab in the editor UI. +There are two ways to create custom zone layouts, window layout and table layout. These can also be thought of as additive and subtractive models. +The additive window layout model starts with a blank layout and supports adding zones that can be dragged and resized similar to windows. + +![FancyZones Window Editor Mode](WindowEditor.png) The subtractive table layout model starts with a table layout and allows zones to be created by splitting and merging zones and then resizing the gutter between zones. +To merge two zone, press and hold the left mouse button and drag the mouse until a second zone is selected, then release the button and a popup menu will show up. -![Fancy Zones Table Editor Mode](TableEditor.png) +![FancyZones Table Editor Mode](TableEditor.png) The backlog for the utility can be found [here](https://github.com/Microsoft/PowerToys/tree/master/doc/planning/FancyZonesBacklog.md) and the source code is [here](https://github.com/Microsoft/PowerToys/tree/master/src/modules/fancyzones). +# Snapping a window to two zones (EXPERIMENTAL) + +If two zones are adjacent, a window can be snapped to the sum of their area (rounded to the minimum rectangle that contains both). When the mouse cursor in near the common edge of two zones, both zones are activated simultaneously, allowing to drop the window on both. +**NOTE:** when snapping a window to two zones, restoring the window when the app is restarted is not supported yet. + +![Two Zones Activation](TwoZonesActivation.png) + # Shortcut Keys | Shortcut | Action | | ----------- | ----------- | | Win + ` | Launches editor (this shortcut is editable in the settings dialog) | -| Win+Ctrl+\ | Cycles through saved layouts with the corresponding number of zones | -| Win+Left/Right Arrow | Move focused window between zones (only if Override snap hotkeys setting is enabled, in that case only the `Win+Left Arrow` and `Win+Right Arrow` are overriden, while the `Win+Up Arrow` and `Win+Down Arrow` keep working as usual) | +| Win+Left/Right Arrow | Move focused window between zones (only if `Override Windows Snap hotkeys` setting is turned on, in that case only the `Win+Left Arrow` and `Win+Right Arrow` are overriden, while the `Win+Up Arrow` and `Win+Down Arrow` keep working as usual) | + +FancyZones doesn't override the Windows 10 `Win+Shift+Arrow` to quickly move a window to an adjacent monitor. # Settings | Setting | Description | | --------- | ------------- | | Configure the zone editor hotkey | To change the default hotkey, click on the textbox (it's not necessary to select or delete the text) and then press on the keyboard the desired key combination | | Enable zones while dragging with the shift key | Toggles between auto-snap mode with the shift key disabling snapping during a drag and manual snap mode where pressing the shift key during a drag enables snapping | -| Override Windows Snap hotkeys (win+arrow) to move between zones | When this option is on and Fancy Zones is running, it overrides two Windows Snap keys: `Win+Left Arrow` and `Win+Right Arrow` | -| Flash zones when the active FancyZones layout changes | Briefly flash the zone layout when the layout changes or a new virtual desktop is activated | -| Keep windows in their zones when the screen resolution changes | After a screen resolution change, if this setting is enabled, Fancy Zones will resize and reposition windows into the zones they were previously in | -| Keep windows in their zones when the active FancyZones layout changes | When this option is on, Fancy Zones will resize and position windows into the new zone layout by maintaining the previous zone number location of each window | +| Override Windows Snap hotkeys (Win+Arrow) to move between zones | When this option is on and FancyZones is running, it overrides two Windows Snap keys: `Win+Left Arrow` and `Win+Right Arrow` | +| Keep windows in their zones when the screen resolution changes | After a screen resolution change, if this setting is enabled, FancyZones will resize and reposition windows into the zones they were previously in | +| Keep windows in their zones when the active FancyZones layout changes | When this option is on, FancyZones will resize and position windows into the new zone layout by maintaining the previous zone number location of each window | | Keep windows in their zones when the active virtual desktop changes | If an application is pinned to all virtual desktops, this setting will keep that window in the same zone on all desktops | | Move newly created windows to the last known zone | Automatically move a newly opened window into the last zone location that application was in | -| Follow mouse cursor instead of focus when launching editor in a multi screen environment | When this option is on, the editor hotkey will launch the editor on the monitor where the mouse cursor is, when this option is off, the editor hotkey will launch the editor on monitor where the current active window is | -| Zone Highlight Color (Default #0078D7) | the color that a zone becomes when it is the active drop target during a window drag | +| Follow mouse cursor instead of focus when launching editor in a multi-monitor environment | When this option is on, the editor hotkey will launch the editor on the monitor where the mouse cursor is, when this option is off, the editor hotkey will launch the editor on monitor where the current active window is | +| Show zones on all monitors while dragging a window | By default FancyZones shows only the zones available on the current monitor, this feature may have performance impact when turned on | +| Show zones on all monitors while dragging a window | When the zones are activated, the dragged window is made transparent to improve the zones visibility | +| Zone highlight color (Default #008CFF) | The color that a zone becomes when it is the active drop target during a window drag | +| Zone Inactive color (Default #F5FCFF) | The color that zones become when they are not an active drop during a window drag | +| Zone border color (Default #FFFFFF) | The color of the border of active and inactive zones | +| Zone opacity (%) (Default 50%) | The percentage of opacity of active and inactive zones | | Exclude applications from snapping to zones | Add the applications name, or part of the name, one per line (e.g., adding `Notepa` will match both `Notepad.exe` and `Notepad++.exe`, to match only `Notepad.exe` add the `.exe` extension) | -![Fancy Zones Settings UI](FancyZonesSettings.png) +![FancyZones Settings UI](FancyZonesSettings1.png) + +![FancyZones Settings UI](FancyZonesSettings2.png) diff --git a/src/modules/fancyzones/TableEditor.png b/src/modules/fancyzones/TableEditor.png index 6aea729924..2d49618217 100644 Binary files a/src/modules/fancyzones/TableEditor.png and b/src/modules/fancyzones/TableEditor.png differ diff --git a/src/modules/fancyzones/TwoZonesActivation.png b/src/modules/fancyzones/TwoZonesActivation.png new file mode 100644 index 0000000000..9f64d2cc7d Binary files /dev/null and b/src/modules/fancyzones/TwoZonesActivation.png differ diff --git a/src/modules/fancyzones/WindowEditor.png b/src/modules/fancyzones/WindowEditor.png index 877055f242..1f0c0c432b 100644 Binary files a/src/modules/fancyzones/WindowEditor.png and b/src/modules/fancyzones/WindowEditor.png differ diff --git a/src/modules/fancyzones/dll/FancyZonesModule.vcxproj b/src/modules/fancyzones/dll/FancyZonesModule.vcxproj index 9120dab1b3..f873bf2a62 100644 --- a/src/modules/fancyzones/dll/FancyZonesModule.vcxproj +++ b/src/modules/fancyzones/dll/FancyZonesModule.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {48804216-2A0E-4168-A6D8-9CD068D14227} Win32Proj fancyzones - 10.0 + 10.0.17134.0 fancyzones @@ -37,6 +38,7 @@ + @@ -62,7 +64,6 @@ Disabled true _DEBUG;FANCYZONES_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h ..\;..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;..\..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) MultiThreadedDebug @@ -84,7 +85,6 @@ true true NDEBUG;FANCYZONES_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h ..\;..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;..\..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) MultiThreaded @@ -132,5 +132,7 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + \ No newline at end of file diff --git a/src/modules/fancyzones/dll/dllmain.cpp b/src/modules/fancyzones/dll/dllmain.cpp index 767b136ca9..a5c5ea4f90 100644 --- a/src/modules/fancyzones/dll/dllmain.cpp +++ b/src/modules/fancyzones/dll/dllmain.cpp @@ -10,24 +10,25 @@ #include #include #include +#include extern "C" IMAGE_DOS_HEADER __ImageBase; -BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { - case DLL_PROCESS_ATTACH: - Trace::RegisterProvider(); - break; + case DLL_PROCESS_ATTACH: + Trace::RegisterProvider(); + break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; - case DLL_PROCESS_DETACH: - Trace::UnregisterProvider(); - break; + case DLL_PROCESS_DETACH: + Trace::UnregisterProvider(); + break; } return TRUE; } @@ -45,13 +46,12 @@ public: // nullptr as the last element of the array. Nullptr can also be retured for empty list. virtual PCWSTR* get_events() override { - static PCWSTR events[] = { ll_keyboard, win_hook_event, nullptr }; - return events; + return nullptr; } // Return JSON with the configuration options. // These are the settings shown on the settings page along with their current values. - virtual bool get_config(_Out_ PWSTR buffer, _Out_ int *buffer_size) override + virtual bool get_config(_Out_ PWSTR buffer, _Out_ int* buffer_size) override { return m_settings->GetConfig(buffer, buffer_size); } @@ -75,8 +75,37 @@ public: { if (!m_app) { + InitializeWinhookEventIds(); Trace::FancyZones::EnableFancyZones(true); m_app = MakeFancyZones(reinterpret_cast(&__ImageBase), m_settings); + + s_llKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL); + if (!s_llKeyboardHook) + { + MessageBoxW(NULL, L"Cannot install keyboard listener.", L"PowerToys - FancyZones", MB_OK | MB_ICONERROR); + } + + std::array events_to_subscribe = { + EVENT_SYSTEM_MOVESIZESTART, + EVENT_SYSTEM_MOVESIZEEND, + EVENT_OBJECT_NAMECHANGE, + EVENT_OBJECT_UNCLOAKED, + EVENT_OBJECT_SHOW, + EVENT_OBJECT_CREATE + }; + for (const auto event : events_to_subscribe) + { + auto hook = SetWinEventHook(event, event, nullptr, WinHookProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); + if (hook) + { + m_staticWinEventHooks.emplace_back(hook); + } + else + { + MessageBoxW(NULL, L"Cannot install Windows event listener.", L"PowerToys - FancyZones", MB_OK | MB_ICONERROR); + } + } + if (m_app) { m_app->Run(); @@ -96,27 +125,14 @@ public: return (m_app != nullptr); } - // Handle incoming event, data is event-specific + // PowertoyModuleIface method, unused virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override { - if (m_app) - { - if (wcscmp(name, ll_keyboard) == 0) - { - // Return 1 if the keypress is to be suppressed (not forwarded to Windows), otherwise return 0. - return HandleKeyboardHookEvent(reinterpret_cast(data)); - } - else if (wcscmp(name, win_hook_event) == 0) - { - // Return value is ignored - HandleWinHookEvent(reinterpret_cast(data)); - } - } return 0; } - virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override { } - virtual void signal_system_menu_action(const wchar_t* name) override { } + virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override {} + virtual void signal_system_menu_action(const wchar_t* name) override {} // Destroy the powertoy and free memory virtual void destroy() override @@ -130,67 +146,129 @@ public: app_name = GET_RESOURCE_STRING(IDS_FANCYZONES); m_settings = MakeFancyZonesSettings(reinterpret_cast(&__ImageBase), FancyZonesModule::get_name()); JSONHelpers::FancyZonesDataInstance().LoadFancyZonesData(); + s_instance = this; } private: void Disable(bool const traceEvent) { - if (m_app) { - if (traceEvent) + if (m_app) + { + if (traceEvent) { Trace::FancyZones::EnableFancyZones(false); } m_app->Destroy(); m_app = nullptr; m_settings->ResetCallback(); + + if (s_llKeyboardHook) + { + if (UnhookWindowsHookEx(s_llKeyboardHook)) + { + s_llKeyboardHook = nullptr; + } + } + + m_staticWinEventHooks.erase(std::remove_if(begin(m_staticWinEventHooks), + end(m_staticWinEventHooks), + [](const HWINEVENTHOOK hook) { + return UnhookWinEvent(hook); + }), + end(m_staticWinEventHooks)); + if (m_objectLocationWinEventHook) + { + if (UnhookWinEvent(m_objectLocationWinEventHook)) + { + m_objectLocationWinEventHook = nullptr; + } + } } } intptr_t HandleKeyboardHookEvent(LowlevelKeyboardEvent* data) noexcept; void HandleWinHookEvent(WinHookEvent* data) noexcept; - void MoveSizeStart(HWND window, POINT const& ptScreen) noexcept; - void MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept; - void MoveSizeUpdate(POINT const& ptScreen) noexcept; winrt::com_ptr m_app; winrt::com_ptr m_settings; std::wstring app_name; + + static inline FancyZonesModule* s_instance; + static inline HHOOK s_llKeyboardHook; + + std::vector m_staticWinEventHooks; + HWINEVENTHOOK m_objectLocationWinEventHook; + + static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) + { + LowlevelKeyboardEvent event; + if (nCode == HC_ACTION && wParam == WM_KEYDOWN) + { + event.lParam = reinterpret_cast(lParam); + event.wParam = wParam; + if (s_instance) + { + return s_instance->HandleKeyboardHookEvent(&event); + } + } + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + static void CALLBACK WinHookProc(HWINEVENTHOOK winEventHook, + DWORD event, + HWND window, + LONG object, + LONG child, + DWORD eventThread, + DWORD eventTime) + { + WinHookEvent data{ event, window, object, child, eventThread, eventTime }; + if (s_instance) + { + s_instance->HandleWinHookEvent(&data); + } + } }; intptr_t FancyZonesModule::HandleKeyboardHookEvent(LowlevelKeyboardEvent* data) noexcept { - if (data->wParam == WM_KEYDOWN) - { - return m_app.as()->OnKeyDown(data->lParam) ? 1 : 0; - } - return 0; + return m_app.as()->OnKeyDown(data->lParam); } void FancyZonesModule::HandleWinHookEvent(WinHookEvent* data) noexcept { - POINT ptScreen; - GetPhysicalCursorPos(&ptScreen); - + auto fzCallback = m_app.as(); switch (data->event) { case EVENT_SYSTEM_MOVESIZESTART: { - MoveSizeStart(data->hwnd, ptScreen); + fzCallback->HandleWinHookEvent(data); + if (!m_objectLocationWinEventHook) + { + m_objectLocationWinEventHook = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, + EVENT_OBJECT_LOCATIONCHANGE, + nullptr, + WinHookProc, + 0, + 0, + WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); + } } break; case EVENT_SYSTEM_MOVESIZEEND: { - MoveSizeEnd(data->hwnd, ptScreen); + if (UnhookWinEvent(m_objectLocationWinEventHook)) + { + m_objectLocationWinEventHook = nullptr; + } + fzCallback->HandleWinHookEvent(data); } break; case EVENT_OBJECT_LOCATIONCHANGE: { - if (m_app.as()->InMoveSize()) - { - MoveSizeUpdate(ptScreen); - } + fzCallback->HandleWinHookEvent(data); } break; @@ -210,10 +288,7 @@ void FancyZonesModule::HandleWinHookEvent(WinHookEvent* data) noexcept case EVENT_OBJECT_SHOW: case EVENT_OBJECT_CREATE: { - if (data->idObject == OBJID_WINDOW) - { - m_app.as()->WindowCreated(data->hwnd); - } + fzCallback->HandleWinHookEvent(data); } break; @@ -222,30 +297,7 @@ void FancyZonesModule::HandleWinHookEvent(WinHookEvent* data) noexcept } } -void FancyZonesModule::MoveSizeStart(HWND window, POINT const& ptScreen) noexcept +extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create() { - if (auto monitor = MonitorFromPoint(ptScreen, MONITOR_DEFAULTTONULL)) - { - m_app.as()->MoveSizeStart(window, monitor, ptScreen); - } + return new FancyZonesModule(); } - -void FancyZonesModule::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept -{ - m_app.as()->MoveSizeEnd(window, ptScreen); -} - -void FancyZonesModule::MoveSizeUpdate(POINT const& ptScreen) noexcept -{ - if (auto monitor = MonitorFromPoint(ptScreen, MONITOR_DEFAULTTONULL)) - { - m_app.as()->MoveSizeUpdate(monitor, ptScreen); - } -} - -extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create() -{ - return new FancyZonesModule(); -} - - diff --git a/src/modules/fancyzones/dll/packages.config b/src/modules/fancyzones/dll/packages.config index feed8b8b86..b19f343a52 100644 --- a/src/modules/fancyzones/dll/packages.config +++ b/src/modules/fancyzones/dll/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/src/modules/fancyzones/dll/pch.h b/src/modules/fancyzones/dll/pch.h index 4ec7b87312..8b7ac0aeae 100644 --- a/src/modules/fancyzones/dll/pch.h +++ b/src/modules/fancyzones/dll/pch.h @@ -3,6 +3,8 @@ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include #include +#include +#include #include #include #include diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs index 374d6cc95e..8e4a8035e2 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs @@ -88,7 +88,7 @@ namespace FancyZonesEditor.Properties { } /// - /// Looks up a localized string similar to Choose your layout. + /// Looks up a localized string similar to Choose your layout for this desktop. /// public static string Choose_Layout { get { diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx index 525faf0d25..27ab979a8f 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx @@ -127,7 +127,7 @@ Cancel - Choose your layout + Choose your layout for this desktop Custom diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/StringUtils.cs b/src/modules/fancyzones/editor/FancyZonesEditor/StringUtils.cs index 8dc4837d54..027003477b 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/StringUtils.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/StringUtils.cs @@ -16,7 +16,7 @@ namespace FancyZonesEditor.Utils return str; } - return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "-" + x.ToString() : x.ToString())).ToLower(); + return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "-" + x.ToString() : x.ToString())).ToLowerInvariant(); } } } diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index 02f924ef05..f041958280 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -1,24 +1,21 @@ #include "pch.h" -#include "common/dpi_aware.h" -#include "common/on_thread_executor.h" + +#include +#include +#include #include "FancyZones.h" #include "lib/Settings.h" #include "lib/ZoneWindow.h" -#include "lib/RegistryHelpers.h" #include "lib/JsonHelpers.h" #include "lib/ZoneSet.h" +#include "lib/WindowMoveHandler.h" +#include "lib/FancyZonesWinHookEventIDs.h" +#include "lib/util.h" #include "trace.h" #include "VirtualDesktopUtils.h" -#include -#include -#include -#include -#include -#include - -#include +#include enum class DisplayChangeType { @@ -29,8 +26,6 @@ enum class DisplayChangeType Initialization }; -extern "C" IMAGE_DOS_HEADER __ImageBase; - namespace std { template<> @@ -49,7 +44,8 @@ struct FancyZones : public winrt::implements& settings) noexcept : m_hinstance(hinstance), - m_settings(settings) + m_settings(settings), + m_windowMoveHandler(settings) { m_settings->SetCallback(this); } @@ -65,26 +61,70 @@ public: InMoveSize() noexcept { std::shared_lock readLock(m_lock); - return m_inMoveSize; + return m_windowMoveHandler.InMoveSize(); + } + + void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen) noexcept + { + std::unique_lock writeLock(m_lock); + m_windowMoveHandler.MoveSizeStart(window, monitor, ptScreen, m_zoneWindowMap); + } + + void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen) noexcept + { + std::unique_lock writeLock(m_lock); + m_windowMoveHandler.MoveSizeUpdate(monitor, ptScreen, m_zoneWindowMap); + } + + void MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept + { + std::unique_lock writeLock(m_lock); + m_windowMoveHandler.MoveSizeEnd(window, ptScreen, m_zoneWindowMap); } IFACEMETHODIMP_(void) - MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen) noexcept; - IFACEMETHODIMP_(void) - MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen) noexcept; - IFACEMETHODIMP_(void) - MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept; + HandleWinHookEvent(const WinHookEvent* data) noexcept + { + const auto wparam = reinterpret_cast(data->hwnd); + const LONG lparam = 0; + std::shared_lock readLock(m_lock); + switch (data->event) + { + case EVENT_SYSTEM_MOVESIZESTART: + PostMessageW(m_window, WM_PRIV_MOVESIZESTART, wparam, lparam); + break; + case EVENT_SYSTEM_MOVESIZEEND: + PostMessageW(m_window, WM_PRIV_MOVESIZEEND, wparam, lparam); + break; + case EVENT_OBJECT_LOCATIONCHANGE: + PostMessageW(m_window, WM_PRIV_LOCATIONCHANGE, wparam, lparam); + break; + case EVENT_OBJECT_NAMECHANGE: + PostMessageW(m_window, WM_PRIV_NAMECHANGE, wparam, lparam); + break; + + case EVENT_OBJECT_UNCLOAKED: + case EVENT_OBJECT_SHOW: + case EVENT_OBJECT_CREATE: + if (data->idObject == OBJID_WINDOW) + { + PostMessageW(m_window, WM_PRIV_WINDOWCREATED, wparam, lparam); + } + break; + } + } + IFACEMETHODIMP_(void) VirtualDesktopChanged() noexcept; IFACEMETHODIMP_(void) VirtualDesktopInitialize() noexcept; - IFACEMETHODIMP_(void) - WindowCreated(HWND window) noexcept; IFACEMETHODIMP_(bool) OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept; IFACEMETHODIMP_(void) ToggleEditor() noexcept; IFACEMETHODIMP_(void) SettingsChanged() noexcept; + + void WindowCreated(HWND window) noexcept; // IZoneWindowHost IFACEMETHODIMP_(void) @@ -150,9 +190,6 @@ public: void OnDisplayChange(DisplayChangeType changeType) noexcept; void AddZoneWindow(HMONITOR monitor, PCWSTR deviceId) noexcept; - void MoveWindowIntoZoneByIndex(HWND window, HMONITOR monitor, int index) noexcept; - void MoveWindowIntoZoneByIndexSet(HWND window, HMONITOR monitor, const std::vector& indexSet) noexcept; - protected: static LRESULT CALLBACK s_WndProc(HWND, UINT, WPARAM, LPARAM) noexcept; @@ -181,19 +218,12 @@ private: } }; - bool IsInterestingWindow(HWND window) noexcept; - bool IsCursorTypeIndicatingSizeEvent(); void UpdateZoneWindows() noexcept; void MoveWindowsOnDisplayChange() noexcept; - void UpdateDragState(HWND window, require_write_lock) noexcept; void CycleActiveZoneSet(DWORD vkCode) noexcept; bool OnSnapHotkey(DWORD vkCode) noexcept; - void MoveSizeStartInternal(HWND window, HMONITOR monitor, POINT const& ptScreen, require_write_lock) noexcept; - void MoveSizeEndInternal(HWND window, POINT const& ptScreen, require_write_lock) noexcept; - void MoveSizeUpdateInternal(HMONITOR monitor, POINT const& ptScreen, require_write_lock) noexcept; - void HandleVirtualDesktopUpdates(HANDLE fancyZonesDestroyedEvent) noexcept; - void RegisterVirtualDesktopUpdates(std::unordered_set& currentVirtualDesktopIds) noexcept; + void RegisterVirtualDesktopUpdates(std::vector& ids) noexcept; void RegisterNewWorkArea(GUID virtualDesktopId, HMONITOR monitor) noexcept; bool IsNewWorkArea(GUID virtualDesktopId, HMONITOR monitor) noexcept; @@ -201,19 +231,14 @@ private: std::vector> GetRawMonitorData() noexcept; std::vector GetMonitorsSorted() noexcept; - bool MoveWindowIntoZoneByDirection(HMONITOR monitor, HWND window, DWORD vkCode, bool cycle); const HINSTANCE m_hinstance{}; - HKEY m_virtualDesktopsRegKey{ nullptr }; - mutable std::shared_mutex m_lock; HWND m_window{}; - 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_dragEnabled{}; // True if we should be showing zone hints while dragging + WindowMoveHandler m_windowMoveHandler; + std::map> m_zoneWindowMap; // Map of monitor to ZoneWindow (one per monitor) - winrt::com_ptr m_zoneWindowMoveSize; // "Active" ZoneWindow, where the move/size is happening. Will update as drag moves between monitors. winrt::com_ptr m_settings{}; GUID m_currentVirtualDesktopId{}; // UUID of the current virtual desktop. Is GUID_NULL until first VD switch per session. std::unordered_map> m_processedWorkAreas; // Work area is defined by monitor and virtual desktop id. @@ -223,9 +248,12 @@ private: OnThreadExecutor m_dpiUnawareThread; OnThreadExecutor m_virtualDesktopTrackerThread; - static UINT WM_PRIV_VDCHANGED; // Message to get back on to the UI thread when virtual desktop changes - static UINT WM_PRIV_VDINIT; // Message to get back to the UI thread when FancyZones are initialized - static UINT WM_PRIV_EDITOR; // Message to get back on to the UI thread when the editor exits + static UINT WM_PRIV_VD_INIT; // Scheduled when FancyZones is initialized + static UINT WM_PRIV_VD_SWITCH; // Scheduled when virtual desktop switch occurs + static UINT WM_PRIV_VD_UPDATE; // Scheduled on virtual desktops update (creation/deletion) + static UINT WM_PRIV_EDITOR; // Scheduled when the editor exits + + static UINT WM_PRIV_LOWLEVELKB; // Scheduled when we receive a key down press // Did we terminate the editor or was it closed cleanly? enum class EditorExitKind : byte @@ -235,9 +263,11 @@ private: }; }; -UINT FancyZones::WM_PRIV_VDCHANGED = RegisterWindowMessage(L"{128c2cb0-6bdf-493e-abbe-f8705e04aa95}"); -UINT FancyZones::WM_PRIV_VDINIT = RegisterWindowMessage(L"{469818a8-00fa-4069-b867-a1da484fcd9a}"); +UINT FancyZones::WM_PRIV_VD_INIT = RegisterWindowMessage(L"{469818a8-00fa-4069-b867-a1da484fcd9a}"); +UINT FancyZones::WM_PRIV_VD_SWITCH = RegisterWindowMessage(L"{128c2cb0-6bdf-493e-abbe-f8705e04aa95}"); +UINT FancyZones::WM_PRIV_VD_UPDATE = RegisterWindowMessage(L"{b8b72b46-f42f-4c26-9e20-29336cf2f22e}"); UINT FancyZones::WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}"); +UINT FancyZones::WM_PRIV_LOWLEVELKB = RegisterWindowMessage(L"{763c03a3-03d9-4cde-8d71-f0358b0b4b52}"); // IFancyZones IFACEMETHODIMP_(void) @@ -268,12 +298,8 @@ FancyZones::Run() noexcept } }) .wait(); - if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VirtualDesktops", 0, KEY_ALL_ACCESS, &m_virtualDesktopsRegKey) == ERROR_SUCCESS) - { - m_terminateVirtualDesktopTrackerEvent.reset(CreateEvent(nullptr, FALSE, FALSE, nullptr)); - m_virtualDesktopTrackerThread.submit( - OnThreadExecutor::task_t{ std::bind(&FancyZones::HandleVirtualDesktopUpdates, this, m_terminateVirtualDesktopTrackerEvent.get()) }); - } + m_terminateVirtualDesktopTrackerEvent.reset(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + m_virtualDesktopTrackerThread.submit(OnThreadExecutor::task_t{ [&] { VirtualDesktopUtils::HandleVirtualDesktopUpdates(m_window, WM_PRIV_VD_UPDATE, m_terminateVirtualDesktopTrackerEvent.get()); } }); } // IFancyZones @@ -292,58 +318,23 @@ FancyZones::Destroy() noexcept { SetEvent(m_terminateVirtualDesktopTrackerEvent.get()); } - if (m_virtualDesktopsRegKey) - { - RegCloseKey(m_virtualDesktopsRegKey); - m_virtualDesktopsRegKey = nullptr; - } -} - -// IFancyZonesCallback -IFACEMETHODIMP_(void) -FancyZones::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen) noexcept -{ - if (IsInterestingWindow(window)) - { - std::unique_lock writeLock(m_lock); - MoveSizeStartInternal(window, monitor, ptScreen, writeLock); - } -} - -// IFancyZonesCallback -IFACEMETHODIMP_(void) -FancyZones::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen) noexcept -{ - std::unique_lock writeLock(m_lock); - MoveSizeUpdateInternal(monitor, ptScreen, writeLock); -} - -// IFancyZonesCallback -IFACEMETHODIMP_(void) -FancyZones::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept -{ - if (window == m_windowMoveSize || IsInterestingWindow(window)) - { - std::unique_lock writeLock(m_lock); - MoveSizeEndInternal(window, ptScreen, writeLock); - } } // IFancyZonesCallback IFACEMETHODIMP_(void) FancyZones::VirtualDesktopChanged() noexcept { - // VirtualDesktopChanged is called from another thread but results in new windows being created. - // Jump over to the UI thread to handle it. + // VirtualDesktopChanged is called from a reentrant WinHookProc function, therefore we must postpone the actual logic + // until we're in FancyZones::WndProc, which is not reentrant. std::shared_lock readLock(m_lock); - PostMessage(m_window, WM_PRIV_VDCHANGED, 0, 0); + PostMessage(m_window, WM_PRIV_VD_SWITCH, 0, 0); } // IFancyZonesCallback IFACEMETHODIMP_(void) FancyZones::VirtualDesktopInitialize() noexcept { - PostMessage(m_window, WM_PRIV_VDINIT, 0, 0); + PostMessage(m_window, WM_PRIV_VD_INIT, 0, 0); } // IFancyZonesCallback @@ -351,7 +342,7 @@ IFACEMETHODIMP_(void) FancyZones::WindowCreated(HWND window) noexcept { std::shared_lock readLock(m_lock); - if (m_settings->GetSettings()->appLastZone_moveWindows && IsInterestingWindow(window)) + if (m_settings->GetSettings()->appLastZone_moveWindows && IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray)) { for (const auto& [monitor, zoneWindow] : m_zoneWindowMap) { @@ -376,7 +367,7 @@ FancyZones::WindowCreated(HWND window) noexcept int zoneIndex = fancyZonesData.GetAppLastZoneIndex(window, zoneWindow->UniqueId(), guidString.get()); if (zoneIndex != -1) { - MoveWindowIntoZoneByIndex(window, monitor, zoneIndex); + m_windowMoveHandler.MoveWindowIntoZoneByIndex(window, monitor, zoneIndex, m_zoneWindowMap); break; } } @@ -391,7 +382,7 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept { // Return true to swallow the keyboard event bool const shift = GetAsyncKeyState(VK_SHIFT) & 0x8000; - bool const win = GetAsyncKeyState(VK_LWIN) & 0x8000; + bool const win = GetAsyncKeyState(VK_LWIN) & 0x8000 || GetAsyncKeyState(VK_RWIN) & 0x8000; if (win && !shift) { bool const ctrl = GetAsyncKeyState(VK_CONTROL) & 0x8000; @@ -410,9 +401,10 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept { if (m_settings->GetSettings()->overrideSnapHotkeys) { - // Win+Left, Win+Right will cycle through Zones in the active ZoneSet Trace::FancyZones::OnKeyDown(info->vkCode, win, ctrl, false /*inMoveSize*/); - return OnSnapHotkey(info->vkCode); + // Win+Left, Win+Right will cycle through Zones in the active ZoneSet when WM_PRIV_LOWLEVELKB's handled + PostMessageW(m_window, WM_PRIV_LOWLEVELKB, 0, info->vkCode); + return true; } } } @@ -424,7 +416,8 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept // CycleActiveZoneSet(info->vkCode); // return false; //} - if (m_dragEnabled && shift) + + if (m_windowMoveHandler.IsDragEnabled() && shift) { return true; } @@ -600,13 +593,28 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa default: { - if (message == WM_PRIV_VDCHANGED) + POINT ptScreen; + GetPhysicalCursorPos(&ptScreen); + + if (message == WM_PRIV_LOWLEVELKB) + { + OnSnapHotkey(static_cast(lparam)); + } + else if (message == WM_PRIV_VD_INIT) + { + OnDisplayChange(DisplayChangeType::Initialization); + } + else if (message == WM_PRIV_VD_SWITCH) { OnDisplayChange(DisplayChangeType::VirtualDesktop); } - else if (message == WM_PRIV_VDINIT) + else if (message == WM_PRIV_VD_UPDATE) { - OnDisplayChange(DisplayChangeType::Initialization); + std::vector ids{}; + if (VirtualDesktopUtils::GetVirtualDesktopIds(ids)) + { + RegisterVirtualDesktopUpdates(ids); + } } else if (message == WM_PRIV_EDITOR) { @@ -622,6 +630,31 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa m_terminateEditorEvent.release(); } } + else if (message == WM_PRIV_MOVESIZESTART) + { + auto hwnd = reinterpret_cast(wparam); + if (auto monitor = MonitorFromPoint(ptScreen, MONITOR_DEFAULTTONULL)) + { + MoveSizeStart(hwnd, monitor, ptScreen); + } + } + else if (message == WM_PRIV_MOVESIZEEND) + { + auto hwnd = reinterpret_cast(wparam); + MoveSizeEnd(hwnd, ptScreen); + } + else if (message == WM_PRIV_LOCATIONCHANGE && InMoveSize()) + { + if (auto monitor = MonitorFromPoint(ptScreen, MONITOR_DEFAULTTONULL)) + { + MoveSizeUpdate(monitor, ptScreen); + } + } + else if (message == WM_PRIV_WINDOWCREATED) + { + auto hwnd = reinterpret_cast(wparam); + WindowCreated(hwnd); + } else { return DefWindowProc(window, message, wparam, lparam); @@ -632,25 +665,25 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa return 0; } + void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept { if (changeType == DisplayChangeType::VirtualDesktop || changeType == DisplayChangeType::Initialization) { - // Explorer persists this value to the registry on a per session basis but only after - // the first virtual desktop switch happens. If the user hasn't switched virtual desktops in this session - // then this value will be empty. This means loading the first virtual desktop's configuration can be - // funky the first time we load up at boot since the user will not have switched virtual desktops yet. GUID currentVirtualDesktopId{}; - if (SUCCEEDED(RegistryHelpers::GetCurrentVirtualDesktop(¤tVirtualDesktopId))) + if (VirtualDesktopUtils::GetCurrentVirtualDesktopId(¤tVirtualDesktopId)) { - std::unique_lock writeLock(m_lock); m_currentVirtualDesktopId = currentVirtualDesktopId; } - else + if (changeType == DisplayChangeType::Initialization) { - // TODO: Use the previous "Desktop 1" fallback - // Need to maintain a map of desktop name to virtual desktop uuid + std::vector ids{}; + if (VirtualDesktopUtils::GetVirtualDesktopIds(ids) && !ids.empty()) + { + JSONHelpers::FancyZonesDataInstance().UpdatePrimaryDesktopData(ids[0]); + JSONHelpers::FancyZonesDataInstance().RemoveDeletedDesktops(ids); + } } } @@ -707,30 +740,6 @@ void FancyZones::AddZoneWindow(HMONITOR monitor, PCWSTR deviceId) noexcept } } -void FancyZones::MoveWindowIntoZoneByIndex(HWND window, HMONITOR monitor, int index) noexcept -{ - std::shared_lock readLock(m_lock); - MoveWindowIntoZoneByIndexSet(window, monitor, { index }); -} - -void FancyZones::MoveWindowIntoZoneByIndexSet(HWND window, HMONITOR monitor, const std::vector& indexSet) noexcept -{ - std::shared_lock readLock(m_lock); - if (window != m_windowMoveSize) - { - const HMONITOR hm = (monitor != nullptr) ? monitor : MonitorFromWindow(window, MONITOR_DEFAULTTONULL); - if (hm) - { - auto zoneWindow = m_zoneWindowMap.find(hm); - if (zoneWindow != m_zoneWindowMap.end()) - { - const auto& zoneWindowPtr = zoneWindow->second; - zoneWindowPtr->MoveWindowIntoZoneByIndexSet(window, indexSet); - } - } - } -} - LRESULT CALLBACK FancyZones::s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept { auto thisRef = reinterpret_cast(GetWindowLongPtr(window, GWLP_USERDATA)); @@ -745,53 +754,6 @@ LRESULT CALLBACK FancyZones::s_WndProc(HWND window, UINT message, WPARAM wparam, DefWindowProc(window, message, wparam, lparam); } -bool FancyZones::IsInterestingWindow(HWND window) noexcept -{ - auto filtered = get_fancyzones_filtered_window(window); - if (!filtered.zonable) - { - return false; - } - // Filter out user specified apps - CharUpperBuffW(filtered.process_path.data(), (DWORD)filtered.process_path.length()); - if (m_settings) - { - const auto& excludedAppsArray = m_settings->GetSettings()->excludedAppsArray; - if (find_app_name_in_path(filtered.process_path, excludedAppsArray)) - { - return false; - } - } - return true; -} - -bool FancyZones::IsCursorTypeIndicatingSizeEvent() -{ - CURSORINFO cursorInfo = { 0 }; - cursorInfo.cbSize = sizeof(cursorInfo); - - if (::GetCursorInfo(&cursorInfo)) - { - if (::LoadCursor(NULL, IDC_SIZENS) == cursorInfo.hCursor) - { - return true; - } - if (::LoadCursor(NULL, IDC_SIZEWE) == cursorInfo.hCursor) - { - return true; - } - if (::LoadCursor(NULL, IDC_SIZENESW) == cursorInfo.hCursor) - { - return true; - } - if (::LoadCursor(NULL, IDC_SIZENWSE) == cursorInfo.hCursor) - { - return true; - } - } - return false; -} - void FancyZones::UpdateZoneWindows() noexcept { auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM data) -> BOOL { @@ -842,63 +804,18 @@ void FancyZones::MoveWindowsOnDisplayChange() noexcept { // i is off by 1 since 0 is special. auto strongThis = reinterpret_cast(data); - strongThis->MoveWindowIntoZoneByIndex(window, nullptr, i - 1); + std::unique_lock writeLock(strongThis->m_lock); + strongThis->m_windowMoveHandler.MoveWindowIntoZoneByIndex(window, nullptr, i - 1, strongThis->m_zoneWindowMap); } return TRUE; }; EnumWindows(callback, reinterpret_cast(this)); } -void FancyZones::UpdateDragState(HWND window, require_write_lock) noexcept -{ - const bool shift = GetAsyncKeyState(VK_SHIFT) & 0x8000; - const bool mouseL = GetAsyncKeyState(VK_LBUTTON) & 0x8000; - const bool mouseR = GetAsyncKeyState(VK_RBUTTON) & 0x8000; - const bool mouseM = GetAsyncKeyState(VK_MBUTTON) & 0x8000; - const bool mouseX1 = GetAsyncKeyState(VK_XBUTTON1) & 0x8000; - const bool mouseX2 = GetAsyncKeyState(VK_XBUTTON2) & 0x8000; - - // Note, Middle, X1 and X2 can also be used in addition to R/L - bool mouse = mouseM | mouseX1 | mouseX2; - // If the user has swapped their Right and Left Buttons, use the "Right" equivalent - if (GetSystemMetrics(SM_SWAPBUTTON)) - { - mouse |= mouseL; - } - else - { - mouse |= mouseR; - } - - if (m_settings->GetSettings()->shiftDrag) - { - m_dragEnabled = (shift | mouse); - } - else - { - m_dragEnabled = !(shift | mouse); - } - - static bool warning_shown = false; - if (!is_process_elevated() && IsProcessOfWindowElevated(window)) - { - m_dragEnabled = false; - if (!warning_shown && !is_cant_drag_elevated_warning_disabled()) - { - std::vector actions = { - notifications::link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_LEARN_MORE), L"https://aka.ms/powertoysDetectedElevatedHelp" }, - notifications::link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN), L"powertoys://cant_drag_elevated_disable/" } - }; - notifications::show_toast_with_activations(GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED), {}, std::move(actions)); - warning_shown = true; - } - } -} - void FancyZones::CycleActiveZoneSet(DWORD vkCode) noexcept { auto window = GetForegroundWindow(); - if (IsInterestingWindow(window)) + if (IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray)) { const HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL); if (monitor) @@ -918,19 +835,20 @@ void FancyZones::CycleActiveZoneSet(DWORD vkCode) noexcept bool FancyZones::OnSnapHotkey(DWORD vkCode) noexcept { auto window = GetForegroundWindow(); - if (IsInterestingWindow(window)) + if (IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray)) { const HMONITOR current = MonitorFromWindow(window, MONITOR_DEFAULTTONULL); if (current) { std::vector monitorInfo = GetMonitorsSorted(); - if (monitorInfo.size() > 1) + if (monitorInfo.size() > 1 && m_settings->GetSettings()->moveWindowAcrossMonitors) { // Multi monitor environment. auto currMonitorInfo = std::find(std::begin(monitorInfo), std::end(monitorInfo), current); do { - if (MoveWindowIntoZoneByDirection(*currMonitorInfo, window, vkCode, false /* cycle through zones */)) + std::unique_lock writeLock(m_lock); + if (m_windowMoveHandler.MoveWindowIntoZoneByDirection(*currMonitorInfo, window, vkCode, false /* cycle through zones */, m_zoneWindowMap)) { return true; } @@ -956,215 +874,23 @@ bool FancyZones::OnSnapHotkey(DWORD vkCode) noexcept else { // Single monitor environment. - return MoveWindowIntoZoneByDirection(current, window, vkCode, true /* cycle through zones */); + std::unique_lock writeLock(m_lock); + return m_windowMoveHandler.MoveWindowIntoZoneByDirection(current, window, vkCode, true /* cycle through zones */, m_zoneWindowMap); } } } return false; } -void FancyZones::MoveSizeStartInternal(HWND window, HMONITOR monitor, POINT const& ptScreen, require_write_lock writeLock) noexcept -{ - if (IsCursorTypeIndicatingSizeEvent()) - { - return; - } - m_inMoveSize = true; - - auto iter = m_zoneWindowMap.find(monitor); - if (iter == end(m_zoneWindowMap)) - { - return; - } - - m_windowMoveSize = window; - - // This updates m_dragEnabled depending on if the shift key is being held down. - UpdateDragState(window, writeLock); - - if (m_dragEnabled) - { - m_zoneWindowMoveSize = iter->second; - m_zoneWindowMoveSize->MoveSizeEnter(window, m_dragEnabled); - if (m_settings->GetSettings()->showZonesOnAllMonitors) - { - for (auto [keyMonitor, zoneWindow] : m_zoneWindowMap) - { - // Skip calling ShowZoneWindow for iter->second (m_zoneWindowMoveSize) since it - // was already called in MoveSizeEnter - const bool moveSizeEnterCalled = zoneWindow == m_zoneWindowMoveSize; - if (zoneWindow && !moveSizeEnterCalled) - { - zoneWindow->ShowZoneWindow(); - } - } - } - } - else if (m_zoneWindowMoveSize) - { - m_zoneWindowMoveSize->RestoreOrginalTransparency(); - m_zoneWindowMoveSize = nullptr; - for (auto [keyMonitor, zoneWindow] : m_zoneWindowMap) - { - if (zoneWindow) - { - zoneWindow->HideZoneWindow(); - } - } - } -} - -void FancyZones::MoveSizeEndInternal(HWND window, POINT const& ptScreen, require_write_lock) noexcept -{ - m_inMoveSize = false; - m_dragEnabled = false; - m_windowMoveSize = nullptr; - if (m_zoneWindowMoveSize) - { - auto zoneWindow = std::move(m_zoneWindowMoveSize); - zoneWindow->MoveSizeEnd(window, ptScreen); - } - else - { - ::RemoveProp(window, ZONE_STAMP); - - auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL); - if (monitor) - { - auto zoneWindow = m_zoneWindowMap.find(monitor); - if (zoneWindow != m_zoneWindowMap.end()) - { - const auto zoneWindowPtr = zoneWindow->second; - const auto activeZoneSet = zoneWindowPtr->ActiveZoneSet(); - if (activeZoneSet) - { - wil::unique_cotaskmem_string guidString; - if (SUCCEEDED_LOG(StringFromCLSID(activeZoneSet->Id(), &guidString))) - { - JSONHelpers::FancyZonesDataInstance().RemoveAppLastZone(window, zoneWindowPtr->UniqueId(), guidString.get()); - } - } - } - } - } - - // Also, hide all windows (regardless of settings) - for (auto [keyMonitor, zoneWindow] : m_zoneWindowMap) - { - if (zoneWindow) - { - zoneWindow->HideZoneWindow(); - } - } -} - -void FancyZones::MoveSizeUpdateInternal(HMONITOR monitor, POINT const& ptScreen, require_write_lock writeLock) noexcept -{ - if (m_inMoveSize) - { - // This updates m_dragEnabled depending on if the shift key is being held down. - UpdateDragState(m_windowMoveSize, writeLock); - - if (m_zoneWindowMoveSize) - { - // Update the ZoneWindow already handling move/size - if (!m_dragEnabled) - { - // Drag got disabled, tell it to cancel and hide all windows - m_zoneWindowMoveSize = nullptr; - - for (auto [keyMonitor, zoneWindow] : m_zoneWindowMap) - { - if (zoneWindow) - { - zoneWindow->RestoreOrginalTransparency(); - zoneWindow->HideZoneWindow(); - } - } - } - else - { - auto iter = m_zoneWindowMap.find(monitor); - if (iter != m_zoneWindowMap.end()) - { - if (iter->second != m_zoneWindowMoveSize) - { - // The drag has moved to a different monitor. - m_zoneWindowMoveSize->RestoreOrginalTransparency(); - - if (!m_settings->GetSettings()->showZonesOnAllMonitors) - { - m_zoneWindowMoveSize->HideZoneWindow(); - } - m_zoneWindowMoveSize = iter->second; - m_zoneWindowMoveSize->MoveSizeEnter(m_windowMoveSize, m_zoneWindowMoveSize->IsDragEnabled()); - } - - for (auto [keyMonitor, zoneWindow] : m_zoneWindowMap) - { - zoneWindow->MoveSizeUpdate(ptScreen, m_dragEnabled); - } - } - } - } - else if (m_dragEnabled) - { - // We'll get here if the user presses/releases shift while dragging. - // Restart the drag on the ZoneWindow that m_windowMoveSize is on - MoveSizeStartInternal(m_windowMoveSize, monitor, ptScreen, writeLock); - MoveSizeUpdateInternal(monitor, ptScreen, writeLock); - } - } -} - -void FancyZones::HandleVirtualDesktopUpdates(HANDLE fancyZonesDestroyedEvent) noexcept -{ - HANDLE regKeyEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); - HANDLE events[2] = { regKeyEvent, fancyZonesDestroyedEvent }; - while (1) - { - if (RegNotifyChangeKeyValue(HKEY_CURRENT_USER, TRUE, REG_NOTIFY_CHANGE_LAST_SET, regKeyEvent, TRUE) != ERROR_SUCCESS) - { - return; - } - if (WaitForMultipleObjects(2, events, FALSE, INFINITE) != (WAIT_OBJECT_0 + 0)) - { - // if fancyZonesDestroyedEvent is signalized or WaitForMultipleObjects failed, terminate thread execution - return; - } - DWORD bufferCapacity; - const WCHAR* key = L"VirtualDesktopIDs"; - // request regkey binary buffer capacity only - if (RegQueryValueExW(m_virtualDesktopsRegKey, key, 0, nullptr, nullptr, &bufferCapacity) != ERROR_SUCCESS) - { - return; - } - std::unique_ptr buffer = std::make_unique(bufferCapacity); - // request regkey binary content - if (RegQueryValueExW(m_virtualDesktopsRegKey, key, 0, nullptr, buffer.get(), &bufferCapacity) != ERROR_SUCCESS) - { - return; - } - const size_t guidSize = sizeof(GUID); - std::unordered_set temp; - temp.reserve(bufferCapacity / guidSize); - for (size_t i = 0; i < bufferCapacity; i += guidSize) - { - GUID* guid = reinterpret_cast(buffer.get() + i); - temp.insert(*guid); - } - RegisterVirtualDesktopUpdates(temp); - } -} - -void FancyZones::RegisterVirtualDesktopUpdates(std::unordered_set& currentVirtualDesktopIds) noexcept +void FancyZones::RegisterVirtualDesktopUpdates(std::vector& ids) noexcept { + std::unordered_set activeVirtualDesktops(std::begin(ids), std::end(ids)); std::unique_lock writeLock(m_lock); bool modified{ false }; - for (auto it = begin(m_processedWorkAreas); it != end(m_processedWorkAreas);) + for (auto it = std::begin(m_processedWorkAreas); it != std::end(m_processedWorkAreas);) { - auto iter = currentVirtualDesktopIds.find(it->first); - if (iter == currentVirtualDesktopIds.end()) + auto iter = activeVirtualDesktops.find(it->first); + if (iter == activeVirtualDesktops.end()) { // if we couldn't find the GUID in currentVirtualDesktopIds, we must remove it from both m_processedWorkAreas and deviceInfoMap wil::unique_cotaskmem_string virtualDesktopId; @@ -1176,7 +902,7 @@ void FancyZones::RegisterVirtualDesktopUpdates(std::unordered_set& current } else { - currentVirtualDesktopIds.erase(it->first); // virtual desktop already in map, skip it + activeVirtualDesktops.erase(it->first); // virtual desktop already in map, skip it ++it; } } @@ -1185,7 +911,7 @@ void FancyZones::RegisterVirtualDesktopUpdates(std::unordered_set& current JSONHelpers::FancyZonesDataInstance().SaveFancyZonesData(); } // register new virtual desktops, if any - for (const auto& id : currentVirtualDesktopIds) + for (const auto& id : activeVirtualDesktops) { m_processedWorkAreas[id] = std::vector(); } @@ -1252,17 +978,6 @@ std::vector> FancyZones::GetRawMonitorData() noexcept return monitorInfo; } -bool FancyZones::MoveWindowIntoZoneByDirection(HMONITOR monitor, HWND window, DWORD vkCode, bool cycle) -{ - auto iter = m_zoneWindowMap.find(monitor); - if (iter != std::end(m_zoneWindowMap)) - { - const auto& zoneWindowPtr = iter->second; - return zoneWindowPtr->MoveWindowIntoZoneByDirection(window, vkCode, cycle); - } - return false; -} - winrt::com_ptr MakeFancyZones(HINSTANCE hinstance, const winrt::com_ptr& settings) noexcept { if (!settings) diff --git a/src/modules/fancyzones/lib/FancyZones.h b/src/modules/fancyzones/lib/FancyZones.h index 47b368098d..698cd2af8c 100644 --- a/src/modules/fancyzones/lib/FancyZones.h +++ b/src/modules/fancyzones/lib/FancyZones.h @@ -4,6 +4,8 @@ interface IZoneWindow; interface IFancyZonesSettings; interface IZoneSet; +struct WinHookEvent; + interface __declspec(uuid("{50D3F0F5-736E-4186-BDF4-3D6BEE150C3A}")) IFancyZones : public IUnknown { /** @@ -21,47 +23,16 @@ interface __declspec(uuid("{50D3F0F5-736E-4186-BDF4-3D6BEE150C3A}")) IFancyZones */ interface __declspec(uuid("{2CB37E8F-87E6-4AEC-B4B2-E0FDC873343F}")) IFancyZonesCallback : public IUnknown { - /** - * @returns Boolean indicating whether a move/size operation is currently active. - */ - IFACEMETHOD_(bool, InMoveSize)() = 0; - /** - * A window is being moved or resized. Track down window position and give zone layout - * hints if dragging functionality is enabled. - * - * @param window Handle of window being moved or resized. - * @param monitor Handle of monitor on which windows is moving / resizing. - * @param ptScreen Cursor coordinates. - */ - IFACEMETHOD_(void, MoveSizeStart)(HWND window, HMONITOR monitor, POINT const& ptScreen) = 0; - /** - * A window has changed location, shape, or size. Track down window position and give zone layout - * hints if dragging functionality is enabled. - * - * @param monitor Handle of monitor on which windows is moving / resizing. - * @param ptScreen Cursor coordinates. - */ - IFACEMETHOD_(void, MoveSizeUpdate)(HMONITOR monitor, POINT const& ptScreen) = 0; - /** - * The movement or resizing of a window has finished. Assign window to the zone if it - * is dropped within zone borders. - * - * @param window Handle of window being moved or resized. - * @param ptScreen Cursor coordinates where window is droped. - */ - IFACEMETHOD_(void, MoveSizeEnd)(HWND window, POINT const& ptScreen) = 0; /** * Inform FancyZones that user has switched between virtual desktops. */ IFACEMETHOD_(void, VirtualDesktopChanged)() = 0; /** - * Inform FancyZones that new window is created. FancyZones will try to assign it to the - * zone insde active zone layout (if information about last zone, in which window was located - * before being closed, is available). + * Callback from WinEventHook to FancyZones * - * @param window Handle of newly created window. + * @param data Handle of window being moved or resized. */ - IFACEMETHOD_(void, WindowCreated)(HWND window) = 0; + IFACEMETHOD_(void, HandleWinHookEvent)(const WinHookEvent* data) = 0; /** * Process keyboard event. * diff --git a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj index 947117192e..7abb16def1 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} Win32Proj lib - 10.0 + 10.0.17134.0 FancyZonesLib @@ -61,7 +62,6 @@ Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) - true pch.h stdcpplatest ..\;..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;..\..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) @@ -81,7 +81,6 @@ true true NDEBUG;_LIB;%(PreprocessorDefinitions) - true pch.h stdcpplatest ..\;..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;..\..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) @@ -96,20 +95,22 @@ + - + + Create @@ -119,6 +120,7 @@ + @@ -132,11 +134,14 @@ + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + \ No newline at end of file diff --git a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters index af912e3803..de21273593 100644 --- a/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters +++ b/src/modules/fancyzones/lib/FancyZonesLib.vcxproj.filters @@ -30,9 +30,6 @@ Header Files - - Header Files - Header Files @@ -51,6 +48,12 @@ Header Files + + Header Files + + + Header Files + @@ -83,6 +86,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/src/modules/fancyzones/lib/FancyZonesWinHookEventIDs.cpp b/src/modules/fancyzones/lib/FancyZonesWinHookEventIDs.cpp new file mode 100644 index 0000000000..d3e59b4b4a --- /dev/null +++ b/src/modules/fancyzones/lib/FancyZonesWinHookEventIDs.cpp @@ -0,0 +1,24 @@ +#include "pch.h" + +#include + +#include "FancyZonesWinHookEventIDs.h" + +UINT WM_PRIV_MOVESIZESTART; +UINT WM_PRIV_MOVESIZEEND; +UINT WM_PRIV_LOCATIONCHANGE; +UINT WM_PRIV_NAMECHANGE; +UINT WM_PRIV_WINDOWCREATED; + +std::once_flag init_flag; + +void InitializeWinhookEventIds() +{ + std::call_once(init_flag, [&] { + WM_PRIV_MOVESIZESTART = RegisterWindowMessage(L"{f48def23-df42-4c0f-a13d-3eb4a9e204d4}"); + WM_PRIV_MOVESIZEEND = RegisterWindowMessage(L"{805d643c-804d-4728-b533-907d760ebaf0}"); + WM_PRIV_LOCATIONCHANGE = RegisterWindowMessage(L"{d56c5ee7-58e5-481c-8c4f-8844cf4d0347}"); + WM_PRIV_NAMECHANGE = RegisterWindowMessage(L"{b7b30c61-bfa0-4d95-bcde-fc4f2cbf6d76}"); + WM_PRIV_WINDOWCREATED = RegisterWindowMessage(L"{bdb10669-75da-480a-9ec4-eeebf09a02d7}"); + }); +} diff --git a/src/modules/fancyzones/lib/FancyZonesWinHookEventIDs.h b/src/modules/fancyzones/lib/FancyZonesWinHookEventIDs.h new file mode 100644 index 0000000000..3f7212fb17 --- /dev/null +++ b/src/modules/fancyzones/lib/FancyZonesWinHookEventIDs.h @@ -0,0 +1,9 @@ +#pragma once + +extern UINT WM_PRIV_MOVESIZESTART; +extern UINT WM_PRIV_MOVESIZEEND; +extern UINT WM_PRIV_LOCATIONCHANGE; +extern UINT WM_PRIV_NAMECHANGE; +extern UINT WM_PRIV_WINDOWCREATED; + +void InitializeWinhookEventIds(); diff --git a/src/modules/fancyzones/lib/JsonHelpers.cpp b/src/modules/fancyzones/lib/JsonHelpers.cpp index 5ff3abc28a..6ad1eef413 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.cpp +++ b/src/modules/fancyzones/lib/JsonHelpers.cpp @@ -1,6 +1,5 @@ #include "pch.h" #include "JsonHelpers.h" -#include "RegistryHelpers.h" #include "ZoneSet.h" #include "trace.h" @@ -11,22 +10,10 @@ #include #include #include +#include namespace { - // Needed for migration of applied zonesets from registry - struct ZoneSetPersistedDataOLD - { - static constexpr inline size_t MAX_ZONES = 40; - DWORD Version{ VERSION_PERSISTEDDATA }; - WORD LayoutId{}; - DWORD ZoneCount{}; - JSONHelpers::ZoneSetLayoutType Layout{}; - DWORD PaddingInner{}; - DWORD PaddingOuter{}; - RECT Zones[MAX_ZONES]{}; - }; - // From Settings.cs constexpr int c_focusModelId = 0xFFFF; constexpr int c_rowsModelId = 0xFFFE; @@ -37,6 +24,7 @@ namespace const wchar_t* FANCY_ZONES_DATA_FILE = L"zones-settings.json"; const wchar_t* DEFAULT_GUID = L"{00000000-0000-0000-0000-000000000000}"; + const wchar_t* REG_SETTINGS = L"Software\\SuperFancyZones"; std::wstring ExtractVirtualDesktopId(const std::wstring& deviceId) { @@ -321,6 +309,65 @@ namespace JSONHelpers } } + void FancyZonesData::UpdatePrimaryDesktopData(const std::wstring& desktopId) + { + // Explorer persists current virtual desktop identifier to registry on a per session basis, + // but only after first virtual desktop switch happens. If the user hasn't switched virtual + // desktops in this session value in registry will be empty and we will use default GUID in + // that case (00000000-0000-0000-0000-000000000000). + // This method will go through all our persisted data with default GUID and update it with + // valid one. + auto replaceDesktopId = [&desktopId](const std::wstring& deviceId) { + return deviceId.substr(0, deviceId.rfind('_') + 1) + desktopId; + }; + std::scoped_lock lock{ dataLock }; + for (auto& [path, data] : appZoneHistoryMap) + { + if (ExtractVirtualDesktopId(data.deviceId) == DEFAULT_GUID) + { + data.deviceId = replaceDesktopId(data.deviceId); + } + } + std::vector toReplace{}; + for (const auto& [id, data] : deviceInfoMap) + { + if (ExtractVirtualDesktopId(id) == DEFAULT_GUID) + { + toReplace.push_back(id); + } + } + for (const auto& id : toReplace) + { + auto mapEntry = deviceInfoMap.extract(id); + mapEntry.key() = replaceDesktopId(id); + deviceInfoMap.insert(std::move(mapEntry)); + } + if (activeDeviceId == DEFAULT_GUID) + { + activeDeviceId = replaceDesktopId(activeDeviceId); + } + SaveFancyZonesData(); + } + + void FancyZonesData::RemoveDeletedDesktops(const std::vector& activeDesktops) + { + std::unordered_set active(std::begin(activeDesktops), std::end(activeDesktops)); + std::scoped_lock lock{ dataLock }; + for (auto it = std::begin(deviceInfoMap); it != std::end(deviceInfoMap);) + { + auto foundId = active.find(ExtractVirtualDesktopId(it->first)); + if (foundId == std::end(active)) + { + it = deviceInfoMap.erase(it); + } + else + { + ++it; + } + } + SaveFancyZonesData(); + } + int FancyZonesData::GetAppLastZoneIndex(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const { std::scoped_lock lock{ dataLock }; @@ -640,7 +687,7 @@ namespace JSONHelpers { std::scoped_lock lock{ dataLock }; wchar_t key[256]; - StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", RegistryHelpers::REG_SETTINGS, L"Layouts"); + StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", REG_SETTINGS, L"Layouts"); HKEY hkey; if (RegOpenKeyExW(HKEY_CURRENT_USER, key, 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS) { diff --git a/src/modules/fancyzones/lib/JsonHelpers.h b/src/modules/fancyzones/lib/JsonHelpers.h index 3b5ecd27f0..9a10bc9f0c 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.h +++ b/src/modules/fancyzones/lib/JsonHelpers.h @@ -233,6 +233,8 @@ namespace JSONHelpers void AddDevice(const std::wstring& deviceId); bool RemoveDevicesByVirtualDesktopId(const std::wstring& virtualDesktopId); void CloneDeviceInfo(const std::wstring& source, const std::wstring& destination); + void UpdatePrimaryDesktopData(const std::wstring& desktopId); + void RemoveDeletedDesktops(const std::vector& activeDesktops); int GetAppLastZoneIndex(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); diff --git a/src/modules/fancyzones/lib/RegistryHelpers.h b/src/modules/fancyzones/lib/RegistryHelpers.h deleted file mode 100644 index e16213e4a6..0000000000 --- a/src/modules/fancyzones/lib/RegistryHelpers.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -namespace RegistryHelpers -{ - static PCWSTR REG_SETTINGS = L"Software\\SuperFancyZones"; - static PCWSTR APP_ZONE_HISTORY_SUBKEY = L"AppZoneHistory"; - - inline HRESULT GetCurrentVirtualDesktop(_Out_ GUID* id) - { - *id = GUID_NULL; - - DWORD sessionId; - ProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - - wchar_t sessionKeyPath[256]{}; - RETURN_IF_FAILED( - StringCchPrintfW( - sessionKeyPath, - ARRAYSIZE(sessionKeyPath), - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SessionInfo\\%d\\VirtualDesktops", - sessionId)); - wil::unique_hkey key{}; - GUID value{}; - - if (RegOpenKeyExW(HKEY_CURRENT_USER, sessionKeyPath, 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) - { - DWORD size = sizeof(value); - if (RegQueryValueExW(key.get(), L"CurrentVirtualDesktop", 0, nullptr, reinterpret_cast(&value), &size) == ERROR_SUCCESS) - { - *id = value; - return S_OK; - } - } - return E_FAIL; - } -} \ No newline at end of file diff --git a/src/modules/fancyzones/lib/Settings.cpp b/src/modules/fancyzones/lib/Settings.cpp index cca1041f52..1db305e5c8 100644 --- a/src/modules/fancyzones/lib/Settings.cpp +++ b/src/modules/fancyzones/lib/Settings.cpp @@ -36,9 +36,10 @@ private: PCWSTR name; bool* value; int resourceId; - } m_configBools[9 /* 10 */] = { // "Turning FLASHING_ZONE option off" + } m_configBools[10 /* 11 */] = { // "Turning FLASHING_ZONE option off" { L"fancyzones_shiftDrag", &m_settings.shiftDrag, IDS_SETTING_DESCRIPTION_SHIFTDRAG }, { L"fancyzones_overrideSnapHotkeys", &m_settings.overrideSnapHotkeys, IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS }, + { L"fancyzones_moveWindowAcrossMonitors", &m_settings.moveWindowAcrossMonitors, IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS }, // "Turning FLASHING_ZONE option off" //{ L"fancyzones_zoneSetChange_flashZones", &m_settings.zoneSetChange_flashZones, IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES }, { L"fancyzones_displayChange_moveWindows", &m_settings.displayChange_moveWindows, IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS }, diff --git a/src/modules/fancyzones/lib/Settings.h b/src/modules/fancyzones/lib/Settings.h index 6b6389d295..0ea4e323f8 100644 --- a/src/modules/fancyzones/lib/Settings.h +++ b/src/modules/fancyzones/lib/Settings.h @@ -12,6 +12,7 @@ struct Settings bool zoneSetChange_flashZones = false; bool zoneSetChange_moveWindows = false; bool overrideSnapHotkeys = false; + bool moveWindowAcrossMonitors = false; bool appLastZone_moveWindows = false; bool use_cursorpos_editor_startupscreen = true; bool showZonesOnAllMonitors = false; diff --git a/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp b/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp index 1a8e892854..c060dd47ca 100644 --- a/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp +++ b/src/modules/fancyzones/lib/VirtualDesktopUtils.cpp @@ -7,6 +7,10 @@ namespace VirtualDesktopUtils const CLSID CLSID_ImmersiveShell = { 0xC2F03A33, 0x21F5, 0x47FA, 0xB4, 0xBB, 0x15, 0x63, 0x62, 0xA2, 0xF2, 0x39 }; const wchar_t GUID_EmptyGUID[] = L"{00000000-0000-0000-0000-000000000000}"; + const wchar_t RegCurrentVirtualDesktop[] = L"CurrentVirtualDesktop"; + const wchar_t RegVirtualDesktopIds[] = L"VirtualDesktopIDs"; + const wchar_t RegKeyVirtualDesktops[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VirtualDesktops"; + IServiceProvider* GetServiceProvider() { IServiceProvider* provider{ nullptr }; @@ -46,4 +50,142 @@ namespace VirtualDesktopUtils } return SUCCEEDED(CLSIDFromString(virtualDesktopId.c_str(), desktopId)); } + + bool GetDesktopIdFromCurrentSession(GUID* desktopId) + { + DWORD sessionId; + ProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + + wchar_t sessionKeyPath[256]{}; + RETURN_IF_FAILED( + StringCchPrintfW( + sessionKeyPath, + ARRAYSIZE(sessionKeyPath), + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SessionInfo\\%d\\VirtualDesktops", + sessionId)); + + wil::unique_hkey key{}; + GUID value{}; + if (RegOpenKeyExW(HKEY_CURRENT_USER, sessionKeyPath, 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) + { + DWORD size = sizeof(GUID); + if (RegQueryValueExW(key.get(), RegCurrentVirtualDesktop, 0, nullptr, reinterpret_cast(&value), &size) == ERROR_SUCCESS) + { + *desktopId = value; + return true; + } + } + return false; + } + + bool GetCurrentVirtualDesktopId(GUID* desktopId) + { + if (!GetDesktopIdFromCurrentSession(desktopId)) + { + // Explorer persists current virtual desktop identifier to registry on a per session basis, + // but only after first virtual desktop switch happens. If the user hasn't switched virtual + // desktops (only primary desktop) in this session value in registry will be empty. + // If this value is empty take first element from array of virtual desktops (not kept per session). + std::vector ids{}; + if (!GetVirtualDesktopIds(ids) || ids.empty()) + { + return false; + } + *desktopId = ids[0]; + } + return true; + } + + bool GetVirtualDesktopIds(HKEY hKey, std::vector& ids) + { + if (!hKey) + { + return false; + } + DWORD bufferCapacity; + // request regkey binary buffer capacity only + if (RegQueryValueExW(hKey, RegVirtualDesktopIds, 0, nullptr, nullptr, &bufferCapacity) != ERROR_SUCCESS) + { + return false; + } + std::unique_ptr buffer = std::make_unique(bufferCapacity); + // request regkey binary content + if (RegQueryValueExW(hKey, RegVirtualDesktopIds, 0, nullptr, buffer.get(), &bufferCapacity) != ERROR_SUCCESS) + { + return false; + } + const size_t guidSize = sizeof(GUID); + std::vector temp; + temp.reserve(bufferCapacity / guidSize); + for (size_t i = 0; i < bufferCapacity; i += guidSize) + { + GUID* guid = reinterpret_cast(buffer.get() + i); + temp.push_back(*guid); + } + ids = std::move(temp); + return true; + } + + bool GetVirtualDesktopIds(std::vector& ids) + { + return GetVirtualDesktopIds(GetVirtualDesktopsRegKey(), ids); + } + + bool GetVirtualDesktopIds(std::vector& ids) + { + std::vector guids{}; + if (GetVirtualDesktopIds(guids)) + { + for (auto& guid : guids) + { + wil::unique_cotaskmem_string guidString; + if (SUCCEEDED(StringFromCLSID(guid, &guidString))) + { + ids.push_back(guidString.get()); + } + } + return true; + } + return false; + } + + HKEY OpenVirtualDesktopsRegKey() + { + HKEY hKey{ nullptr }; + if (RegOpenKeyEx(HKEY_CURRENT_USER, RegKeyVirtualDesktops, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) + { + return hKey; + } + return nullptr; + } + + HKEY GetVirtualDesktopsRegKey() + { + static wil::unique_hkey virtualDesktopsKey{ OpenVirtualDesktopsRegKey() }; + return virtualDesktopsKey.get(); + } + + void HandleVirtualDesktopUpdates(HWND window, UINT message, HANDLE terminateEvent) + { + HKEY virtualDesktopsRegKey = GetVirtualDesktopsRegKey(); + if (!virtualDesktopsRegKey) + { + return; + } + HANDLE regKeyEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + HANDLE events[2] = { regKeyEvent, terminateEvent }; + while (1) + { + if (RegNotifyChangeKeyValue(virtualDesktopsRegKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, regKeyEvent, TRUE) != ERROR_SUCCESS) + { + return; + } + if (WaitForMultipleObjects(2, events, FALSE, INFINITE) != (WAIT_OBJECT_0 + 0)) + { + // if terminateEvent is signalized or WaitForMultipleObjects failed, terminate thread execution + return; + } + PostMessage(window, message, 0, 0); + } + } } diff --git a/src/modules/fancyzones/lib/VirtualDesktopUtils.h b/src/modules/fancyzones/lib/VirtualDesktopUtils.h index c92d4b922c..5bf5c1778c 100644 --- a/src/modules/fancyzones/lib/VirtualDesktopUtils.h +++ b/src/modules/fancyzones/lib/VirtualDesktopUtils.h @@ -6,4 +6,9 @@ namespace VirtualDesktopUtils { bool GetWindowDesktopId(HWND topLevelWindow, GUID* desktopId); bool GetZoneWindowDesktopId(IZoneWindow* zoneWindow, GUID* desktopId); + bool GetCurrentVirtualDesktopId(GUID* desktopId); + bool GetVirtualDesktopIds(std::vector& ids); + bool GetVirtualDesktopIds(std::vector& ids); + HKEY GetVirtualDesktopsRegKey(); + void HandleVirtualDesktopUpdates(HWND window, UINT message, HANDLE terminateEvent); } diff --git a/src/modules/fancyzones/lib/WindowMoveHandler.cpp b/src/modules/fancyzones/lib/WindowMoveHandler.cpp new file mode 100644 index 0000000000..2b7ca64aa6 --- /dev/null +++ b/src/modules/fancyzones/lib/WindowMoveHandler.cpp @@ -0,0 +1,362 @@ +#include "pch.h" +#include "WindowMoveHandler.h" + +#include +#include +#include + +#include "lib/Settings.h" +#include "lib/ZoneWindow.h" +#include "lib/util.h" + +extern "C" IMAGE_DOS_HEADER __ImageBase; + +namespace WindowMoveHandlerUtils +{ + bool IsCursorTypeIndicatingSizeEvent() + { + CURSORINFO cursorInfo = { 0 }; + cursorInfo.cbSize = sizeof(cursorInfo); + + if (::GetCursorInfo(&cursorInfo)) + { + if (::LoadCursor(NULL, IDC_SIZENS) == cursorInfo.hCursor) + { + return true; + } + if (::LoadCursor(NULL, IDC_SIZEWE) == cursorInfo.hCursor) + { + return true; + } + if (::LoadCursor(NULL, IDC_SIZENESW) == cursorInfo.hCursor) + { + return true; + } + if (::LoadCursor(NULL, IDC_SIZENWSE) == cursorInfo.hCursor) + { + return true; + } + } + return false; + } +} + + +class WindowMoveHandlerPrivate +{ +public: + WindowMoveHandlerPrivate(const winrt::com_ptr& settings) : + m_settings(settings) + {}; + + bool IsDragEnabled() const noexcept + { + return m_dragEnabled; + } + + bool InMoveSize() const noexcept + { + return m_inMoveSize; + } + + void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept; + void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept; + void MoveSizeEnd(HWND window, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept; + + void MoveWindowIntoZoneByIndexSet(HWND window, HMONITOR monitor, const std::vector& indexSet, const std::map>& zoneWindowMap) noexcept; + bool MoveWindowIntoZoneByDirection(HMONITOR monitor, HWND window, DWORD vkCode, bool cycle, const std::map>& zoneWindowMap); + +private: + void UpdateDragState(HWND window) noexcept; + +private: + winrt::com_ptr m_settings{}; + + HWND m_windowMoveSize{}; // The window that is being moved/sized + bool m_inMoveSize{}; // Whether or not a move/size operation is currently active + winrt::com_ptr 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 +}; + + +WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr& settings) : + pimpl(new WindowMoveHandlerPrivate(settings)) +{ + +} + +WindowMoveHandler::~WindowMoveHandler() +{ + delete pimpl; +} + +bool WindowMoveHandler::InMoveSize() const noexcept +{ + return pimpl->InMoveSize(); +} + +bool WindowMoveHandler::IsDragEnabled() const noexcept +{ + return pimpl->IsDragEnabled(); +} + +void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept +{ + pimpl->MoveSizeStart(window, monitor, ptScreen, zoneWindowMap); +} + +void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept +{ + pimpl->MoveSizeUpdate(monitor, ptScreen, zoneWindowMap); +} + +void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept +{ + pimpl->MoveSizeEnd(window, ptScreen, zoneWindowMap); +} + +void WindowMoveHandler::MoveWindowIntoZoneByIndex(HWND window, HMONITOR monitor, int index, const std::map>& zoneWindowMap) noexcept +{ + pimpl->MoveWindowIntoZoneByIndexSet(window, monitor, { index }, zoneWindowMap); +} + +bool WindowMoveHandler::MoveWindowIntoZoneByDirection(HMONITOR monitor, HWND window, DWORD vkCode, bool cycle, const std::map>& zoneWindowMap) +{ + return pimpl->MoveWindowIntoZoneByDirection(monitor, window, vkCode, cycle, zoneWindowMap); +} + +void WindowMoveHandlerPrivate::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept +{ + if (!IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray) || WindowMoveHandlerUtils::IsCursorTypeIndicatingSizeEvent()) + { + return; + } + + m_inMoveSize = true; + + auto iter = zoneWindowMap.find(monitor); + if (iter == end(zoneWindowMap)) + { + return; + } + + m_windowMoveSize = window; + + // This updates m_dragEnabled depending on if the shift key is being held down. + UpdateDragState(window); + + if (m_dragEnabled) + { + m_zoneWindowMoveSize = iter->second; + m_zoneWindowMoveSize->MoveSizeEnter(window, m_dragEnabled); + if (m_settings->GetSettings()->showZonesOnAllMonitors) + { + for (auto [keyMonitor, zoneWindow] : zoneWindowMap) + { + // Skip calling ShowZoneWindow for iter->second (m_zoneWindowMoveSize) since it + // was already called in MoveSizeEnter + const bool moveSizeEnterCalled = zoneWindow == m_zoneWindowMoveSize; + if (zoneWindow && !moveSizeEnterCalled) + { + zoneWindow->ShowZoneWindow(); + } + } + } + } + else if (m_zoneWindowMoveSize) + { + m_zoneWindowMoveSize->RestoreOrginalTransparency(); + m_zoneWindowMoveSize = nullptr; + for (auto [keyMonitor, zoneWindow] : zoneWindowMap) + { + if (zoneWindow) + { + zoneWindow->HideZoneWindow(); + } + } + } +} + +void WindowMoveHandlerPrivate::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept +{ + if (!m_inMoveSize) + { + return; + } + + // This updates m_dragEnabled depending on if the shift key is being held down. + UpdateDragState(m_windowMoveSize); + + if (m_zoneWindowMoveSize) + { + // Update the ZoneWindow already handling move/size + if (!m_dragEnabled) + { + // Drag got disabled, tell it to cancel and hide all windows + m_zoneWindowMoveSize = nullptr; + + for (auto [keyMonitor, zoneWindow] : zoneWindowMap) + { + if (zoneWindow) + { + zoneWindow->RestoreOrginalTransparency(); + zoneWindow->HideZoneWindow(); + } + } + } + else + { + auto iter = zoneWindowMap.find(monitor); + if (iter != zoneWindowMap.end()) + { + if (iter->second != m_zoneWindowMoveSize) + { + // The drag has moved to a different monitor. + m_zoneWindowMoveSize->RestoreOrginalTransparency(); + + if (!m_settings->GetSettings()->showZonesOnAllMonitors) + { + m_zoneWindowMoveSize->HideZoneWindow(); + } + m_zoneWindowMoveSize = iter->second; + m_zoneWindowMoveSize->MoveSizeEnter(m_windowMoveSize, m_zoneWindowMoveSize->IsDragEnabled()); + } + + for (auto [keyMonitor, zoneWindow] : zoneWindowMap) + { + zoneWindow->MoveSizeUpdate(ptScreen, m_dragEnabled); + } + } + } + } + else if (m_dragEnabled) + { + // We'll get here if the user presses/releases shift while dragging. + // Restart the drag on the ZoneWindow that m_windowMoveSize is on + MoveSizeStart(m_windowMoveSize, monitor, ptScreen, zoneWindowMap); + MoveSizeUpdate(monitor, ptScreen, zoneWindowMap); + } +} + +void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept +{ + if (window != m_windowMoveSize && !IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray)) + { + return; + } + + m_inMoveSize = false; + m_dragEnabled = false; + m_windowMoveSize = nullptr; + if (m_zoneWindowMoveSize) + { + auto zoneWindow = std::move(m_zoneWindowMoveSize); + zoneWindow->MoveSizeEnd(window, ptScreen); + } + else + { + ::RemoveProp(window, ZONE_STAMP); + + auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL); + if (monitor) + { + auto zoneWindow = zoneWindowMap.find(monitor); + if (zoneWindow != zoneWindowMap.end()) + { + const auto zoneWindowPtr = zoneWindow->second; + const auto activeZoneSet = zoneWindowPtr->ActiveZoneSet(); + if (activeZoneSet) + { + wil::unique_cotaskmem_string guidString; + if (SUCCEEDED_LOG(StringFromCLSID(activeZoneSet->Id(), &guidString))) + { + JSONHelpers::FancyZonesDataInstance().RemoveAppLastZone(window, zoneWindowPtr->UniqueId(), guidString.get()); + } + } + } + } + } + + // Also, hide all windows (regardless of settings) + for (auto [keyMonitor, zoneWindow] : zoneWindowMap) + { + if (zoneWindow) + { + zoneWindow->HideZoneWindow(); + } + } +} + +void WindowMoveHandlerPrivate::MoveWindowIntoZoneByIndexSet(HWND window, HMONITOR monitor, const std::vector& indexSet, const std::map>& zoneWindowMap) noexcept +{ + if (window != m_windowMoveSize) + { + const HMONITOR hm = (monitor != nullptr) ? monitor : MonitorFromWindow(window, MONITOR_DEFAULTTONULL); + if (hm) + { + auto zoneWindow = zoneWindowMap.find(hm); + if (zoneWindow != zoneWindowMap.end()) + { + const auto& zoneWindowPtr = zoneWindow->second; + zoneWindowPtr->MoveWindowIntoZoneByIndexSet(window, indexSet); + } + } + } +} + +bool WindowMoveHandlerPrivate::MoveWindowIntoZoneByDirection(HMONITOR monitor, HWND window, DWORD vkCode, bool cycle, const std::map>& zoneWindowMap) +{ + auto iter = zoneWindowMap.find(monitor); + if (iter != std::end(zoneWindowMap)) + { + const auto& zoneWindowPtr = iter->second; + return zoneWindowPtr->MoveWindowIntoZoneByDirection(window, vkCode, cycle); + } + return false; +} + +void WindowMoveHandlerPrivate::UpdateDragState(HWND window) noexcept +{ + const bool shift = GetAsyncKeyState(VK_SHIFT) & 0x8000; + const bool mouseL = GetAsyncKeyState(VK_LBUTTON) & 0x8000; + const bool mouseR = GetAsyncKeyState(VK_RBUTTON) & 0x8000; + const bool mouseM = GetAsyncKeyState(VK_MBUTTON) & 0x8000; + const bool mouseX1 = GetAsyncKeyState(VK_XBUTTON1) & 0x8000; + const bool mouseX2 = GetAsyncKeyState(VK_XBUTTON2) & 0x8000; + + // Note, Middle, X1 and X2 can also be used in addition to R/L + bool mouse = mouseM | mouseX1 | mouseX2; + // If the user has swapped their Right and Left Buttons, use the "Right" equivalent + if (GetSystemMetrics(SM_SWAPBUTTON)) + { + mouse |= mouseL; + } + else + { + mouse |= mouseR; + } + + if (m_settings->GetSettings()->shiftDrag) + { + m_dragEnabled = (shift | mouse); + } + else + { + m_dragEnabled = !(shift | mouse); + } + + static bool warning_shown = false; + if (!is_process_elevated() && IsProcessOfWindowElevated(window)) + { + m_dragEnabled = false; + if (!warning_shown && !is_cant_drag_elevated_warning_disabled()) + { + std::vector actions = { + notifications::link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_LEARN_MORE), L"https://aka.ms/powertoysDetectedElevatedHelp" }, + notifications::link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN), L"powertoys://cant_drag_elevated_disable/" } + }; + notifications::show_toast_with_activations(GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED), {}, std::move(actions)); + warning_shown = true; + } + } +} diff --git a/src/modules/fancyzones/lib/WindowMoveHandler.h b/src/modules/fancyzones/lib/WindowMoveHandler.h new file mode 100644 index 0000000000..572990e706 --- /dev/null +++ b/src/modules/fancyzones/lib/WindowMoveHandler.h @@ -0,0 +1,24 @@ +#pragma once + +interface IFancyZonesSettings; +interface IZoneWindow; + +class WindowMoveHandler +{ +public: + WindowMoveHandler(const winrt::com_ptr& settings); + ~WindowMoveHandler(); + + bool InMoveSize() const noexcept; + bool IsDragEnabled() const noexcept; + + void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept; + void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept; + void MoveSizeEnd(HWND window, POINT const& ptScreen, const std::map>& zoneWindowMap) noexcept; + + void MoveWindowIntoZoneByIndex(HWND window, HMONITOR monitor, int index, const std::map>& zoneWindowMap) noexcept; + bool MoveWindowIntoZoneByDirection(HMONITOR monitor, HWND window, DWORD vkCode, bool cycle, const std::map>& zoneWindowMap); + +private: + class WindowMoveHandlerPrivate* pimpl; +}; \ No newline at end of file diff --git a/src/modules/fancyzones/lib/ZoneSet.cpp b/src/modules/fancyzones/lib/ZoneSet.cpp index 269632727b..15c0d8a4fc 100644 --- a/src/modules/fancyzones/lib/ZoneSet.cpp +++ b/src/modules/fancyzones/lib/ZoneSet.cpp @@ -2,7 +2,6 @@ #include "util.h" #include "lib/ZoneSet.h" -#include "lib/RegistryHelpers.h" #include diff --git a/src/modules/fancyzones/lib/ZoneWindow.cpp b/src/modules/fancyzones/lib/ZoneWindow.cpp index 711b33e623..f8f8507753 100644 --- a/src/modules/fancyzones/lib/ZoneWindow.cpp +++ b/src/modules/fancyzones/lib/ZoneWindow.cpp @@ -5,7 +5,6 @@ #include "ZoneWindow.h" #include "trace.h" #include "util.h" -#include "RegistryHelpers.h" #include #include @@ -213,7 +212,7 @@ public: IFACEMETHODIMP_(void) RestoreOrginalTransparency() noexcept; IFACEMETHODIMP_(bool) - IsDragEnabled() noexcept; + IsDragEnabled() noexcept { return m_dragEnabled; } IFACEMETHODIMP_(void) MoveWindowIntoZoneByIndex(HWND window, int index) noexcept; IFACEMETHODIMP_(void) @@ -223,13 +222,13 @@ public: IFACEMETHODIMP_(void) CycleActiveZoneSet(DWORD vkCode) noexcept; IFACEMETHODIMP_(std::wstring) - UniqueId() noexcept; + UniqueId() noexcept { return { m_uniqueId }; } IFACEMETHODIMP_(std::wstring) - WorkAreaKey() noexcept; + WorkAreaKey() noexcept { return { m_workArea }; } IFACEMETHODIMP_(void) SaveWindowProcessToZoneIndex(HWND window) noexcept; IFACEMETHODIMP_(IZoneSet*) - ActiveZoneSet() noexcept; + ActiveZoneSet() noexcept { return m_activeZoneSet.get(); } IFACEMETHODIMP_(void) ShowZoneWindow() noexcept; IFACEMETHODIMP_(void) @@ -267,15 +266,13 @@ private: static const UINT m_showAnimationDuration = 200; // ms static const UINT m_flashDuration = 700; // ms - HWND m_draggedWindow = nullptr; - long m_draggedWindowExstyle = 0; - COLORREF m_draggedWindowCrKey = RGB(0, 0, 0); - DWORD m_draggedWindowDwFlags = 0; - BYTE m_draggedWindowInitialAlpha = 0; + HWND draggedWindow = nullptr; + long draggedWindowExstyle = 0; + COLORREF draggedWindowCrKey = RGB(0, 0, 0); + DWORD draggedWindowDwFlags = 0; + BYTE draggedWindowInitialAlpha = 0; - ULONG_PTR m_gdiplusToken; - - mutable std::shared_mutex m_mutex; + ULONG_PTR gdiplusToken; }; ZoneWindow::ZoneWindow(HINSTANCE hinstance) @@ -289,14 +286,12 @@ ZoneWindow::ZoneWindow(HINSTANCE hinstance) RegisterClassExW(&wcex); Gdiplus::GdiplusStartupInput gdiplusStartupInput; - Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); + Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); } ZoneWindow::~ZoneWindow() { - RestoreOrginalTransparency(); - - Gdiplus::GdiplusShutdown(m_gdiplusToken); + Gdiplus::GdiplusShutdown(gdiplusToken); } bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, bool flashZones, bool newWorkArea) @@ -349,26 +344,13 @@ bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monit IFACEMETHODIMP ZoneWindow::MoveSizeEnter(HWND window, bool dragEnabled) noexcept { - std::shared_lock lock(m_mutex); - auto windowMoveSize = m_windowMoveSize; - auto hostTransparentActive = m_host->isMakeDraggedWindowTransparentActive(); - lock.unlock(); - - if (windowMoveSize) + if (m_windowMoveSize) { return E_INVALIDARG; } - if (hostTransparentActive) + if (m_host->isMakeDraggedWindowTransparentActive()) { - decltype(m_draggedWindowExstyle) draggedWindowExstyle; - decltype(m_draggedWindow) draggedWindow; - decltype(m_draggedWindowCrKey) draggedWindowCrKey; - decltype(m_draggedWindowInitialAlpha) draggedWindowInitialAlpha; - decltype(m_draggedWindowDwFlags) draggedWindowDwFlags; - - RestoreOrginalTransparency(); - draggedWindowExstyle = GetWindowLong(window, GWL_EXSTYLE); draggedWindow = window; @@ -379,45 +361,27 @@ IFACEMETHODIMP ZoneWindow::MoveSizeEnter(HWND window, bool dragEnabled) noexcept GetLayeredWindowAttributes(window, &draggedWindowCrKey, &draggedWindowInitialAlpha, &draggedWindowDwFlags); SetLayeredWindowAttributes(window, 0, (255 * 50) / 100, LWA_ALPHA); - - std::unique_lock writeLock(m_mutex); - m_draggedWindowExstyle = draggedWindowExstyle; - m_draggedWindow = draggedWindow; - m_draggedWindowCrKey = draggedWindowCrKey; - m_draggedWindowInitialAlpha = draggedWindowInitialAlpha; - m_draggedWindowDwFlags = draggedWindowDwFlags; } - { - std::unique_lock writeLock(m_mutex); - m_dragEnabled = dragEnabled; - m_windowMoveSize = window; - m_drawHints = true; - m_highlightZone = {}; - } - + m_dragEnabled = dragEnabled; + m_windowMoveSize = window; + m_drawHints = true; + m_highlightZone = {}; ShowZoneWindow(); return S_OK; } IFACEMETHODIMP ZoneWindow::MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled) noexcept { - std::shared_lock lock(m_mutex); - auto window = m_window.get(); - lock.unlock(); - bool redraw = false; POINT ptClient = ptScreen; - MapWindowPoints(nullptr, window, &ptClient, 1); + MapWindowPoints(nullptr, m_window.get(), &ptClient, 1); - std::unique_lock writeLock(m_mutex); m_dragEnabled = dragEnabled; if (dragEnabled) { - writeLock.unlock(); auto highlightZone = ZonesFromPoint(ptClient); - writeLock.lock(); redraw = (highlightZone != m_highlightZone); m_highlightZone = std::move(highlightZone); } @@ -427,11 +391,9 @@ IFACEMETHODIMP ZoneWindow::MoveSizeUpdate(POINT const& ptScreen, bool dragEnable redraw = true; } - writeLock.unlock(); - if (redraw) { - InvalidateRect(window, nullptr, true); + InvalidateRect(m_window.get(), nullptr, true); } return S_OK; } @@ -440,74 +402,30 @@ IFACEMETHODIMP ZoneWindow::MoveSizeEnd(HWND window, POINT const& ptScreen) noexc { RestoreOrginalTransparency(); - std::shared_lock lock(m_mutex); - auto windowMoveSize = m_windowMoveSize; - auto thisWindow = m_window.get(); - auto activeZoneSet = m_activeZoneSet; - lock.unlock(); - - if (windowMoveSize != window) + if (m_windowMoveSize != window) { return E_INVALIDARG; } - if (activeZoneSet) + if (m_activeZoneSet) { POINT ptClient = ptScreen; - MapWindowPoints(nullptr, thisWindow, &ptClient, 1); - activeZoneSet->MoveWindowIntoZoneByPoint(window, thisWindow, ptClient); + MapWindowPoints(nullptr, m_window.get(), &ptClient, 1); + m_activeZoneSet->MoveWindowIntoZoneByPoint(window, m_window.get(), ptClient); SaveWindowProcessToZoneIndex(window); } - Trace::ZoneWindow::MoveSizeEnd(activeZoneSet); + Trace::ZoneWindow::MoveSizeEnd(m_activeZoneSet); HideZoneWindow(); - std::unique_lock writeLock(m_mutex); m_windowMoveSize = nullptr; return S_OK; } -IFACEMETHODIMP_(bool) -ZoneWindow::IsDragEnabled() noexcept -{ - std::shared_lock lock(m_mutex); - return m_dragEnabled; -} - -IFACEMETHODIMP_(std::wstring) -ZoneWindow::UniqueId() noexcept -{ - std::shared_lock lock(m_mutex); - return m_uniqueId; -} - -IFACEMETHODIMP_(std::wstring) -ZoneWindow::WorkAreaKey() noexcept -{ - std::shared_lock lock(m_mutex); - return m_workArea; -} - -IFACEMETHODIMP_(IZoneSet*) -ZoneWindow::ActiveZoneSet() noexcept -{ - std::shared_lock lock(m_mutex); - return m_activeZoneSet.get(); -} - IFACEMETHODIMP_(void) ZoneWindow::RestoreOrginalTransparency() noexcept { - std::shared_lock lock(m_mutex); - auto hostTransparentActive = m_host->isMakeDraggedWindowTransparentActive(); - auto draggedWindow = m_draggedWindow; - auto draggedWindowCrKey = m_draggedWindowCrKey; - auto draggedWindowInitialAlpha = m_draggedWindowInitialAlpha; - auto draggedWindowDwFlags = m_draggedWindowDwFlags; - auto draggedWindowExstyle = m_draggedWindowExstyle; - lock.unlock(); - - if (hostTransparentActive && draggedWindow != nullptr) + if (m_host->isMakeDraggedWindowTransparentActive() && draggedWindow != nullptr) { SetLayeredWindowAttributes(draggedWindow, draggedWindowCrKey, draggedWindowInitialAlpha, draggedWindowDwFlags); SetWindowLong(draggedWindow, GWL_EXSTYLE, draggedWindowExstyle); @@ -524,28 +442,18 @@ ZoneWindow::MoveWindowIntoZoneByIndex(HWND window, int index) noexcept IFACEMETHODIMP_(void) ZoneWindow::MoveWindowIntoZoneByIndexSet(HWND window, const std::vector& indexSet) noexcept { - std::shared_lock lock(m_mutex); - auto thisWindow = m_window.get(); - auto activeZoneSet = m_activeZoneSet; - lock.unlock(); - - if (activeZoneSet) + if (m_activeZoneSet) { - activeZoneSet->MoveWindowIntoZoneByIndexSet(window, thisWindow, indexSet, false); + m_activeZoneSet->MoveWindowIntoZoneByIndexSet(window, m_window.get(), indexSet, false); } } IFACEMETHODIMP_(bool) ZoneWindow::MoveWindowIntoZoneByDirection(HWND window, DWORD vkCode, bool cycle) noexcept { - std::shared_lock lock(m_mutex); - auto thisWindow = m_window.get(); - auto activeZoneSet = m_activeZoneSet; - lock.unlock(); - - if (activeZoneSet) + if (m_activeZoneSet) { - if (activeZoneSet->MoveWindowIntoZoneByDirection(window, thisWindow, vkCode, cycle)) + if (m_activeZoneSet->MoveWindowIntoZoneByDirection(window, m_window.get(), vkCode, cycle)) { SaveWindowProcessToZoneIndex(window); return true; @@ -559,14 +467,9 @@ ZoneWindow::CycleActiveZoneSet(DWORD wparam) noexcept { CycleActiveZoneSetInternal(wparam, Trace::ZoneWindow::InputMode::Keyboard); - std::shared_lock lock(m_mutex); - auto windowMoveSize = m_windowMoveSize; - auto window = m_window.get(); - lock.unlock(); - - if (windowMoveSize) + if (m_windowMoveSize) { - InvalidateRect(window, nullptr, true); + InvalidateRect(m_window.get(), nullptr, true); } else { @@ -577,19 +480,15 @@ ZoneWindow::CycleActiveZoneSet(DWORD wparam) noexcept IFACEMETHODIMP_(void) ZoneWindow::SaveWindowProcessToZoneIndex(HWND window) noexcept { - std::shared_lock lock(m_mutex); - auto activeZoneSet = m_activeZoneSet; - lock.unlock(); - - if (activeZoneSet) + if (m_activeZoneSet) { - DWORD zoneIndex = static_cast(activeZoneSet->GetZoneIndexFromWindow(window)); + DWORD zoneIndex = static_cast(m_activeZoneSet->GetZoneIndexFromWindow(window)); if (zoneIndex != -1) { OLECHAR* guidString; - if (StringFromCLSID(activeZoneSet->Id(), &guidString) == S_OK) + if (StringFromCLSID(m_activeZoneSet->Id(), &guidString) == S_OK) { - JSONHelpers::FancyZonesDataInstance().SetAppLastZone(window, UniqueId(), guidString, zoneIndex); + JSONHelpers::FancyZonesDataInstance().SetAppLastZone(window, m_uniqueId, guidString, zoneIndex); } CoTaskMemFree(guidString); @@ -600,43 +499,36 @@ ZoneWindow::SaveWindowProcessToZoneIndex(HWND window) noexcept IFACEMETHODIMP_(void) ZoneWindow::ShowZoneWindow() noexcept { - std::shared_lock lock(m_mutex); auto window = m_window.get(); - HWND windowInsertAfter = m_windowMoveSize; - lock.unlock(); - - if (window) + if (!window) { - { - std::unique_lock writeLock(m_mutex); - m_flashMode = false; - } + return; + } - UINT flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE; + m_flashMode = false; - if (windowInsertAfter == nullptr) - { - windowInsertAfter = HWND_TOPMOST; - } + UINT flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE; - SetWindowPos(window, windowInsertAfter, 0, 0, 0, 0, flags); + HWND windowInsertAfter = m_windowMoveSize; + if (windowInsertAfter == nullptr) + { + windowInsertAfter = HWND_TOPMOST; + } + SetWindowPos(window, windowInsertAfter, 0, 0, 0, 0, flags); + + std::thread{ [=]() { AnimateWindow(window, m_showAnimationDuration, AW_BLEND); InvalidateRect(window, nullptr, true); - } + } }.detach(); } IFACEMETHODIMP_(void) ZoneWindow::HideZoneWindow() noexcept { - std::shared_lock lock(m_mutex); - auto window = m_window.get(); - lock.unlock(); - - if (window) + if (m_window) { - ShowWindow(window, SW_HIDE); - std::unique_lock writeLock(m_mutex); + ShowWindow(m_window.get(), SW_HIDE); m_keyLast = 0; m_windowMoveSize = nullptr; m_drawHints = false; @@ -648,34 +540,27 @@ ZoneWindow::HideZoneWindow() noexcept void ZoneWindow::LoadSettings() noexcept { - JSONHelpers::FancyZonesDataInstance().AddDevice(UniqueId()); + JSONHelpers::FancyZonesDataInstance().AddDevice(m_uniqueId); } void ZoneWindow::InitializeZoneSets(bool newWorkArea) noexcept { - std::shared_lock lock(m_mutex); auto parent = m_host->GetParentZoneWindow(m_monitor); - lock.unlock(); - if (newWorkArea && parent) { // Update device info with device info from parent virtual desktop (if empty). - JSONHelpers::FancyZonesDataInstance().CloneDeviceInfo(parent->UniqueId(), UniqueId()); + JSONHelpers::FancyZonesDataInstance().CloneDeviceInfo(parent->UniqueId(), m_uniqueId); } CalculateZoneSet(); } void ZoneWindow::CalculateZoneSet() noexcept { - std::unique_lock lock(m_mutex); - auto monitor = m_monitor; - lock.unlock(); - const auto& fancyZonesData = JSONHelpers::FancyZonesDataInstance(); - const auto deviceInfoData = fancyZonesData.FindDeviceInfo(UniqueId()); + const auto deviceInfoData = fancyZonesData.FindDeviceInfo(m_uniqueId); const auto& activeDeviceId = fancyZonesData.GetActiveDeviceId(); - if (!activeDeviceId.empty() && activeDeviceId != UniqueId()) + if (!activeDeviceId.empty() && activeDeviceId != m_uniqueId) { return; } @@ -698,11 +583,11 @@ void ZoneWindow::CalculateZoneSet() noexcept auto zoneSet = MakeZoneSet(ZoneSetConfig( zoneSetId, activeZoneSet.type, - monitor, - WorkAreaKey().c_str())); + m_monitor, + m_workArea)); MONITORINFO monitorInfo{}; monitorInfo.cbSize = sizeof(monitorInfo); - if (GetMonitorInfoW(monitor, &monitorInfo)) + if (GetMonitorInfoW(m_monitor, &monitorInfo)) { bool showSpacing = deviceInfoData->showSpacing; int spacing = showSpacing ? deviceInfoData->spacing : 0; @@ -715,37 +600,30 @@ void ZoneWindow::CalculateZoneSet() noexcept void ZoneWindow::UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept { - { - std::unique_lock writeLock(m_mutex); - m_activeZoneSet.copy_from(zoneSet); - } + m_activeZoneSet.copy_from(zoneSet); - if (zoneSet) + if (m_activeZoneSet) { wil::unique_cotaskmem_string zoneSetId; - if (SUCCEEDED_LOG(StringFromCLSID(zoneSet->Id(), &zoneSetId))) + if (SUCCEEDED_LOG(StringFromCLSID(m_activeZoneSet->Id(), &zoneSetId))) { JSONHelpers::ZoneSetData data{ .uuid = zoneSetId.get(), - .type = zoneSet->LayoutType() + .type = m_activeZoneSet->LayoutType() }; - JSONHelpers::FancyZonesDataInstance().SetActiveZoneSet(UniqueId(), data); + JSONHelpers::FancyZonesDataInstance().SetActiveZoneSet(m_uniqueId, data); } } } LRESULT ZoneWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept { - std::shared_lock lock(m_mutex); - auto window = m_window.get(); - lock.unlock(); - switch (message) { case WM_NCDESTROY: { - ::DefWindowProc(window, message, wparam, lparam); - SetWindowLongPtr(window, GWLP_USERDATA, 0); + ::DefWindowProc(m_window.get(), message, wparam, lparam); + SetWindowLongPtr(m_window.get(), GWLP_USERDATA, 0); } break; @@ -759,14 +637,14 @@ LRESULT ZoneWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept wil::unique_hdc hdc{ reinterpret_cast(wparam) }; if (!hdc) { - hdc.reset(BeginPaint(window, &ps)); + hdc.reset(BeginPaint(m_window.get(), &ps)); } OnPaint(hdc); if (wparam == 0) { - EndPaint(window, &ps); + EndPaint(m_window.get(), &ps); } hdc.release(); @@ -775,7 +653,7 @@ LRESULT ZoneWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept default: { - return DefWindowProc(window, message, wparam, lparam); + return DefWindowProc(m_window.get(), message, wparam, lparam); } } return 0; @@ -783,17 +661,8 @@ LRESULT ZoneWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept void ZoneWindow::OnPaint(wil::unique_hdc& hdc) noexcept { - std::shared_lock lock(m_mutex); - auto host = m_host; - auto highlightZone = m_highlightZone; - auto flashMode = m_flashMode; - auto drawHints = m_drawHints; - HWND window = m_window.get(); - auto activeZoneSet = m_activeZoneSet; - lock.unlock(); - RECT clientRect; - GetClientRect(window, &clientRect); + GetClientRect(m_window.get(), &clientRect); wil::unique_hdc hdcMem; HPAINTBUFFER bufferedPaint = BeginBufferedPaint(hdc.get(), &clientRect, BPBF_TOPDOWNDIB, nullptr, &hdcMem); @@ -801,17 +670,17 @@ void ZoneWindow::OnPaint(wil::unique_hdc& hdc) noexcept { ZoneWindowDrawUtils::DrawBackdrop(hdcMem, clientRect); - if (activeZoneSet && host) + if (m_activeZoneSet && m_host) { ZoneWindowDrawUtils::DrawActiveZoneSet(hdcMem, - host->GetZoneColor(), - host->GetZoneBorderColor(), - host->GetZoneHighlightColor(), - host->GetZoneHighlightOpacity(), - activeZoneSet->GetZones(), - highlightZone, - flashMode, - drawHints); + m_host->GetZoneColor(), + m_host->GetZoneBorderColor(), + m_host->GetZoneHighlightColor(), + m_host->GetZoneHighlightOpacity(), + m_activeZoneSet->GetZones(), + m_highlightZone, + m_flashMode, + m_drawHints); } EndBufferedPaint(bufferedPaint, TRUE); @@ -820,56 +689,43 @@ void ZoneWindow::OnPaint(wil::unique_hdc& hdc) noexcept void ZoneWindow::OnKeyUp(WPARAM wparam) noexcept { - std::shared_lock lock(m_mutex); - auto window = m_window.get(); - lock.unlock(); - bool fRedraw = false; Trace::ZoneWindow::KeyUp(wparam); if ((wparam >= '0') && (wparam <= '9')) { CycleActiveZoneSetInternal(static_cast(wparam), Trace::ZoneWindow::InputMode::Keyboard); - InvalidateRect(window, nullptr, true); + InvalidateRect(m_window.get(), nullptr, true); } } std::vector ZoneWindow::ZonesFromPoint(POINT pt) noexcept { - auto activeZoneSet = ActiveZoneSet(); - if (activeZoneSet) + if (m_activeZoneSet) { - return activeZoneSet->ZonesFromPoint(pt); + return m_activeZoneSet->ZonesFromPoint(pt); } return {}; } void ZoneWindow::CycleActiveZoneSetInternal(DWORD wparam, Trace::ZoneWindow::InputMode mode) noexcept { - std::shared_lock lock(m_mutex); - auto activeZoneSet = m_activeZoneSet; - auto keyLast = m_keyLast; - auto keyCycle = m_keyCycle; - auto zoneSets = m_zoneSets; - auto host = m_host; - lock.unlock(); - - Trace::ZoneWindow::CycleActiveZoneSet(activeZoneSet, mode); - if (keyLast != wparam) + Trace::ZoneWindow::CycleActiveZoneSet(m_activeZoneSet, mode); + if (m_keyLast != wparam) { - keyCycle = 0; + m_keyCycle = 0; } - keyLast = wparam; + m_keyLast = wparam; bool loopAround = true; size_t const val = static_cast(wparam - L'0'); size_t i = 0; - for (auto zoneSet : zoneSets) + for (auto zoneSet : m_zoneSets) { if (zoneSet->GetZones().size() == val) { - if (i < keyCycle) + if (i < m_keyCycle) { i++; } @@ -882,25 +738,21 @@ void ZoneWindow::CycleActiveZoneSetInternal(DWORD wparam, Trace::ZoneWindow::Inp } } - if ((keyCycle > 0) && loopAround) + if ((m_keyCycle > 0) && loopAround) { // Cycling through a non-empty group and hit the end - keyCycle = 0; + m_keyCycle = 0; OnKeyUp(wparam); } else { - keyCycle++; + m_keyCycle++; } - if (host) + if (m_host) { - host->MoveWindowsOnActiveZoneSetChange(); + m_host->MoveWindowsOnActiveZoneSetChange(); } - - std::unique_lock writeLock(m_mutex); - m_keyLast = keyLast; - m_keyCycle = keyCycle; m_highlightZone = {}; } @@ -912,13 +764,10 @@ void ZoneWindow::FlashZones() noexcept return; } - std::unique_lock writeLock(m_mutex); m_flashMode = true; - auto window = m_window.get(); - writeLock.unlock(); - ShowWindow(window, SW_SHOWNA); - std::thread([window]() { + ShowWindow(m_window.get(), SW_SHOWNA); + std::thread([window = m_window.get()]() { AnimateWindow(window, m_flashDuration, AW_HIDE | AW_BLEND); }).detach(); } diff --git a/src/modules/fancyzones/lib/fancyzones.rc b/src/modules/fancyzones/lib/fancyzones.rc index 5a0bb1bb13..3b1444bd5e 100644 --- a/src/modules/fancyzones/lib/fancyzones.rc +++ b/src/modules/fancyzones/lib/fancyzones.rc @@ -8,6 +8,7 @@ BEGIN IDS_SETTING_DESCRIPTION "Create window layouts to help make multi-tasking easy" IDS_SETTING_DESCRIPTION_SHIFTDRAG "On: Hold Shift key or any non-primary mouse button to enable zones while dragging" IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS "Override Windows Snap hotkeys (win+arrow) to move windows between zones" + IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS "Move windows between zones across all monitors when snapping with win+arrow" IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS "Keep windows in their zones when the screen resolution changes" IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS "During zone layout changes, windows assigned to a zone will match new size/positions" IDS_SETTING_DESCRIPTION_VIRTUALDESKTOPCHANGE_MOVEWINDOWS "Keep windows pinned to multiple desktops in the same zone when the active desktop changes" diff --git a/src/modules/fancyzones/lib/packages.config b/src/modules/fancyzones/lib/packages.config index feed8b8b86..b19f343a52 100644 --- a/src/modules/fancyzones/lib/packages.config +++ b/src/modules/fancyzones/lib/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/src/modules/fancyzones/lib/pch.h b/src/modules/fancyzones/lib/pch.h index 5cbc577ef5..ac4132707f 100644 --- a/src/modules/fancyzones/lib/pch.h +++ b/src/modules/fancyzones/lib/pch.h @@ -4,6 +4,7 @@ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include #include +#include #include #include #include @@ -13,8 +14,11 @@ #include #include #include -#include +#include #include +#include +#include +#include #pragma comment(lib, "windowsapp") diff --git a/src/modules/fancyzones/lib/resource.h b/src/modules/fancyzones/lib/resource.h index 0b860517bb..984207a5b7 100644 --- a/src/modules/fancyzones/lib/resource.h +++ b/src/modules/fancyzones/lib/resource.h @@ -1,24 +1,25 @@ #define IDS_SETTING_DESCRIPTION_SHIFTDRAG 101 #define IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS 102 -#define IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS 103 -#define IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS 104 -#define IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES 105 -#define IDS_SETTING_DESCRIPTION_VIRTUALDESKTOPCHANGE_MOVEWINDOWS 106 -#define IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS 107 -#define IDS_SETTING_DESCRIPTION_MAKE_DRAGGED_WINDOW_TRANSPARENT 108 -#define IDS_SETTING_DESCRIPTION_ZONECOLOR 109 -#define IDS_SETTING_DESCRIPTION_ZONE_BORDER_COLOR 110 -#define IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR 111 -#define IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS 112 -#define IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN 113 -#define IDS_SETTING_DESCRIPTION 114 -#define IDS_SETTING_LAUNCH_EDITOR_LABEL 115 -#define IDS_SETTING_LAUNCH_EDITOR_BUTTON 116 -#define IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION 117 -#define IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL 118 -#define IDS_SETTING_EXCLCUDED_APPS_DESCRIPTION 119 -#define IDS_SETTINGS_HIGHLIGHT_OPACITY 120 -#define IDS_FANCYZONES 121 -#define IDS_CANT_DRAG_ELEVATED 122 -#define IDS_CANT_DRAG_ELEVATED_LEARN_MORE 123 -#define IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN 124 +#define IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS 103 +#define IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS 104 +#define IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS 105 +#define IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES 106 +#define IDS_SETTING_DESCRIPTION_VIRTUALDESKTOPCHANGE_MOVEWINDOWS 107 +#define IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS 108 +#define IDS_SETTING_DESCRIPTION_MAKE_DRAGGED_WINDOW_TRANSPARENT 109 +#define IDS_SETTING_DESCRIPTION_ZONECOLOR 110 +#define IDS_SETTING_DESCRIPTION_ZONE_BORDER_COLOR 111 +#define IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR 112 +#define IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS 113 +#define IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN 114 +#define IDS_SETTING_DESCRIPTION 115 +#define IDS_SETTING_LAUNCH_EDITOR_LABEL 116 +#define IDS_SETTING_LAUNCH_EDITOR_BUTTON 117 +#define IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION 118 +#define IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL 119 +#define IDS_SETTING_EXCLCUDED_APPS_DESCRIPTION 120 +#define IDS_SETTINGS_HIGHLIGHT_OPACITY 121 +#define IDS_FANCYZONES 122 +#define IDS_CANT_DRAG_ELEVATED 123 +#define IDS_CANT_DRAG_ELEVATED_LEARN_MORE 124 +#define IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN 125 diff --git a/src/modules/fancyzones/lib/trace.cpp b/src/modules/fancyzones/lib/trace.cpp index 91131cd95a..9f51c7d2a0 100644 --- a/src/modules/fancyzones/lib/trace.cpp +++ b/src/modules/fancyzones/lib/trace.cpp @@ -178,6 +178,7 @@ void Trace::SettingsChanged(const Settings& settings) noexcept TraceLoggingBoolean(settings.zoneSetChange_flashZones, "FlashZonesOnZoneSetChange"), TraceLoggingBoolean(settings.zoneSetChange_moveWindows, "MoveWindowsOnZoneSetChange"), TraceLoggingBoolean(settings.overrideSnapHotkeys, "OverrideSnapHotKeys"), + TraceLoggingBoolean(settings.moveWindowAcrossMonitors, "MoveWindowAcrossMonitors"), TraceLoggingBoolean(settings.appLastZone_moveWindows, "MoveWindowsToLastZoneOnAppOpening"), TraceLoggingBoolean(settings.use_cursorpos_editor_startupscreen, "UseCursorPosOnEditorStartup"), TraceLoggingBoolean(settings.showZonesOnAllMonitors, "ShowZonesOnAllMonitors"), diff --git a/src/modules/fancyzones/lib/util.cpp b/src/modules/fancyzones/lib/util.cpp index 675b9f67e1..fa6256e900 100644 --- a/src/modules/fancyzones/lib/util.cpp +++ b/src/modules/fancyzones/lib/util.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "util.h" +#include #include typedef BOOL(WINAPI* GetDpiForMonitorInternalFunc)(HMONITOR, UINT, UINT*, UINT*); @@ -135,3 +136,19 @@ void SizeWindowToRect(HWND window, RECT rect) noexcept // This fixes Issue #365 ::SetWindowPlacement(window, &placement); } + +bool IsInterestingWindow(HWND window, const std::vector& excludedApps) noexcept +{ + auto filtered = get_fancyzones_filtered_window(window); + if (!filtered.zonable) + { + return false; + } + // Filter out user specified apps + CharUpperBuffW(filtered.process_path.data(), (DWORD)filtered.process_path.length()); + if (find_app_name_in_path(filtered.process_path, excludedApps)) + { + return false; + } + return true; +} diff --git a/src/modules/fancyzones/lib/util.h b/src/modules/fancyzones/lib/util.h index be654c8555..9f465b2baf 100644 --- a/src/modules/fancyzones/lib/util.h +++ b/src/modules/fancyzones/lib/util.h @@ -119,3 +119,5 @@ inline BYTE OpacitySettingToAlpha(int opacity) UINT GetDpiForMonitor(HMONITOR monitor) noexcept; void OrderMonitors(std::vector>& monitorInfo); void SizeWindowToRect(HWND window, RECT rect) noexcept; + +bool IsInterestingWindow(HWND window, const std::vector& exludedApps) noexcept; \ No newline at end of file diff --git a/src/modules/fancyzones/tests/UnitTests/FancyZones.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/FancyZones.Spec.cpp index 1a7b6a05b6..273f5a803c 100644 --- a/src/modules/fancyzones/tests/UnitTests/FancyZones.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/FancyZones.Spec.cpp @@ -62,6 +62,7 @@ namespace FancyZonesUnitTests ptSettings.add_hotkey(L"fancyzones_editor_hotkey", IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, settings.editorHotkey); ptSettings.add_bool_toogle(L"fancyzones_shiftDrag", IDS_SETTING_DESCRIPTION_SHIFTDRAG, settings.shiftDrag); ptSettings.add_bool_toogle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, settings.overrideSnapHotkeys); + ptSettings.add_bool_toogle(L"fancyzones_moveWindowAcrossMonitors", IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS, settings.moveWindowAcrossMonitors); ptSettings.add_bool_toogle(L"fancyzones_zoneSetChange_flashZones", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES, settings.zoneSetChange_flashZones); ptSettings.add_bool_toogle(L"fancyzones_displayChange_moveWindows", IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS, settings.displayChange_moveWindows); ptSettings.add_bool_toogle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows); @@ -110,6 +111,7 @@ namespace FancyZonesUnitTests .zoneSetChange_flashZones = false, .zoneSetChange_moveWindows = true, .overrideSnapHotkeys = false, + .moveWindowAcrossMonitors = false, .appLastZone_moveWindows = true, .use_cursorpos_editor_startupscreen = true, .zoneColor = L"#abafee", @@ -138,6 +140,7 @@ namespace FancyZonesUnitTests .zoneSetChange_flashZones = false, .zoneSetChange_moveWindows = true, .overrideSnapHotkeys = false, + .moveWindowAcrossMonitors = false, .appLastZone_moveWindows = true, .use_cursorpos_editor_startupscreen = true, .zoneColor = L"#FAFAFA", @@ -166,6 +169,7 @@ namespace FancyZonesUnitTests .zoneSetChange_flashZones = false, .zoneSetChange_moveWindows = true, .overrideSnapHotkeys = false, + .moveWindowAcrossMonitors = false, .appLastZone_moveWindows = true, .use_cursorpos_editor_startupscreen = true, .showZonesOnAllMonitors = false, @@ -196,6 +200,7 @@ namespace FancyZonesUnitTests .zoneSetChange_flashZones = false, .zoneSetChange_moveWindows = true, .overrideSnapHotkeys = false, + .moveWindowAcrossMonitors = false, .appLastZone_moveWindows = true, .use_cursorpos_editor_startupscreen = true, .showZonesOnAllMonitors = false, @@ -226,6 +231,7 @@ namespace FancyZonesUnitTests .zoneSetChange_flashZones = false, .zoneSetChange_moveWindows = true, .overrideSnapHotkeys = false, + .moveWindowAcrossMonitors = false, .appLastZone_moveWindows = true, .use_cursorpos_editor_startupscreen = true, .showZonesOnAllMonitors = false, @@ -274,6 +280,7 @@ namespace FancyZonesUnitTests ptSettings.add_hotkey(L"fancyzones_editor_hotkey", IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, settings.editorHotkey); ptSettings.add_bool_toogle(L"fancyzones_shiftDrag", IDS_SETTING_DESCRIPTION_SHIFTDRAG, settings.shiftDrag); ptSettings.add_bool_toogle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, settings.overrideSnapHotkeys); + ptSettings.add_bool_toogle(L"fancyzones_moveWindowAcrossMonitors", IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS, settings.moveWindowAcrossMonitors); ptSettings.add_bool_toogle(L"fancyzones_zoneSetChange_flashZones", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES, settings.zoneSetChange_flashZones); ptSettings.add_bool_toogle(L"fancyzones_displayChange_moveWindows", IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS, settings.displayChange_moveWindows); ptSettings.add_bool_toogle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows); diff --git a/src/modules/fancyzones/tests/UnitTests/FancyZonesSettings.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/FancyZonesSettings.Spec.cpp index 4c12122ac8..1e4edd9950 100644 --- a/src/modules/fancyzones/tests/UnitTests/FancyZonesSettings.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/FancyZonesSettings.Spec.cpp @@ -32,6 +32,7 @@ namespace FancyZonesUnitTests Assert::AreEqual(expected.zoneSetChange_flashZones, actual.zoneSetChange_flashZones); Assert::AreEqual(expected.zoneSetChange_moveWindows, actual.zoneSetChange_moveWindows); Assert::AreEqual(expected.overrideSnapHotkeys, actual.overrideSnapHotkeys); + Assert::AreEqual(expected.moveWindowAcrossMonitors, actual.moveWindowAcrossMonitors); Assert::AreEqual(expected.appLastZone_moveWindows, actual.appLastZone_moveWindows); Assert::AreEqual(expected.use_cursorpos_editor_startupscreen, actual.use_cursorpos_editor_startupscreen); Assert::AreEqual(expected.showZonesOnAllMonitors, actual.showZonesOnAllMonitors); @@ -109,6 +110,7 @@ namespace FancyZonesUnitTests values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors); values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); @@ -144,6 +146,7 @@ namespace FancyZonesUnitTests values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors); values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); @@ -173,6 +176,7 @@ namespace FancyZonesUnitTests .zoneSetChange_flashZones = m_defaultSettings.zoneSetChange_flashZones, .zoneSetChange_moveWindows = m_defaultSettings.zoneSetChange_moveWindows, .overrideSnapHotkeys = m_defaultSettings.overrideSnapHotkeys, + .moveWindowAcrossMonitors = m_defaultSettings.moveWindowAcrossMonitors, .appLastZone_moveWindows = m_defaultSettings.appLastZone_moveWindows, .use_cursorpos_editor_startupscreen = m_defaultSettings.use_cursorpos_editor_startupscreen, .showZonesOnAllMonitors = m_defaultSettings.showZonesOnAllMonitors, @@ -215,6 +219,7 @@ namespace FancyZonesUnitTests values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors); values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); @@ -244,6 +249,7 @@ namespace FancyZonesUnitTests values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors); values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); @@ -274,6 +280,7 @@ namespace FancyZonesUnitTests values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors); values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); @@ -305,6 +312,7 @@ namespace FancyZonesUnitTests values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors); values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); @@ -379,6 +387,8 @@ namespace FancyZonesUnitTests IFACEMETHODIMP_(void) MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept {} IFACEMETHODIMP_(void) + HandleWinHookEvent(const WinHookEvent * data) noexcept {} + IFACEMETHODIMP_(void) VirtualDesktopChanged() noexcept {} IFACEMETHODIMP_(void) VirtualDesktopInitialize() noexcept {} @@ -415,6 +425,7 @@ namespace FancyZonesUnitTests .zoneSetChange_flashZones = true, .zoneSetChange_moveWindows = true, .overrideSnapHotkeys = false, + .moveWindowAcrossMonitors = false, .appLastZone_moveWindows = false, .use_cursorpos_editor_startupscreen = true, .showZonesOnAllMonitors = false, @@ -435,6 +446,7 @@ namespace FancyZonesUnitTests values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors); values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); @@ -461,12 +473,12 @@ namespace FancyZonesUnitTests TEST_METHOD (CallbackSetConfig) { bool flag = false; - FZCallback callback(&flag); + winrt::com_ptr callback = winrt::make_self(&flag); json::JsonObject json{}; json.SetNamedValue(L"name", json::JsonValue::CreateStringValue(L"name")); - m_settings->SetCallback(&callback); + m_settings->SetCallback(callback.get()); m_settings->SetConfig(json.Stringify().c_str()); Assert::IsTrue(flag); @@ -475,12 +487,12 @@ namespace FancyZonesUnitTests TEST_METHOD (CallbackCallCustomAction) { bool flag = false; - FZCallback callback(&flag); + winrt::com_ptr callback = winrt::make_self(&flag); json::JsonObject action{}; action.SetNamedValue(L"action_name", json::JsonValue::CreateStringValue(L"ToggledFZEditor")); - m_settings->SetCallback(&callback); + m_settings->SetCallback(callback.get()); m_settings->CallCustomAction(action.Stringify().c_str()); Assert::IsTrue(flag); @@ -489,12 +501,12 @@ namespace FancyZonesUnitTests TEST_METHOD (CallbackCallCustomActionNotToggle) { bool flag = false; - FZCallback callback(&flag); + winrt::com_ptr callback = winrt::make_self(&flag); json::JsonObject action{}; action.SetNamedValue(L"action_name", json::JsonValue::CreateStringValue(L"NOT_ToggledFZEditor")); - m_settings->SetCallback(&callback); + m_settings->SetCallback(callback.get()); m_settings->CallCustomAction(action.Stringify().c_str()); Assert::IsFalse(flag); @@ -503,9 +515,9 @@ namespace FancyZonesUnitTests TEST_METHOD (CallbackGetConfig) { bool flag = false; - FZCallback callback(&flag); + winrt::com_ptr callback = winrt::make_self(&flag); - m_settings->SetCallback(&callback); + m_settings->SetCallback(callback.get()); int bufSize = 0; m_settings->GetConfig(L"", &bufSize); @@ -516,9 +528,9 @@ namespace FancyZonesUnitTests TEST_METHOD (CallbackGetSettings) { bool flag = false; - FZCallback callback(&flag); + winrt::com_ptr callback = winrt::make_self(&flag); - m_settings->SetCallback(&callback); + m_settings->SetCallback(callback.get()); m_settings->GetSettings(); Assert::IsFalse(flag); @@ -547,6 +559,7 @@ namespace FancyZonesUnitTests ptSettings.add_hotkey(L"fancyzones_editor_hotkey", IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, settings.editorHotkey); ptSettings.add_bool_toogle(L"fancyzones_shiftDrag", IDS_SETTING_DESCRIPTION_SHIFTDRAG, settings.shiftDrag); ptSettings.add_bool_toogle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, settings.overrideSnapHotkeys); + ptSettings.add_bool_toogle(L"fancyzones_moveWindowAcrossMonitors", IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS, settings.moveWindowAcrossMonitors); ptSettings.add_bool_toogle(L"fancyzones_zoneSetChange_flashZones", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES, settings.zoneSetChange_flashZones); ptSettings.add_bool_toogle(L"fancyzones_displayChange_moveWindows", IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS, settings.displayChange_moveWindows); ptSettings.add_bool_toogle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows); @@ -578,6 +591,7 @@ namespace FancyZonesUnitTests //values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_moveWindowAcrossMonitors", expected.moveWindowAcrossMonitors); values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); @@ -608,6 +622,7 @@ namespace FancyZonesUnitTests m_ptSettings->add_hotkey(L"fancyzones_editor_hotkey", IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, expected.editorHotkey); m_ptSettings->add_bool_toogle(L"fancyzones_shiftDrag", IDS_SETTING_DESCRIPTION_SHIFTDRAG, expected.shiftDrag); m_ptSettings->add_bool_toogle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, expected.overrideSnapHotkeys); + m_ptSettings->add_bool_toogle(L"fancyzones_moveWindowAcrossMonitors", IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS, expected.moveWindowAcrossMonitors); //m_ptSettings->add_bool_toogle(L"fancyzones_zoneSetChange_flashZones", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES, expected.zoneSetChange_flashZones); m_ptSettings->add_bool_toogle(L"fancyzones_displayChange_moveWindows", IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS, expected.displayChange_moveWindows); m_ptSettings->add_bool_toogle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, expected.zoneSetChange_moveWindows); @@ -680,6 +695,7 @@ namespace FancyZonesUnitTests .zoneSetChange_flashZones = false, .zoneSetChange_moveWindows = true, .overrideSnapHotkeys = false, + .moveWindowAcrossMonitors = false, .appLastZone_moveWindows = true, .use_cursorpos_editor_startupscreen = true, .showZonesOnAllMonitors = false, diff --git a/src/modules/fancyzones/tests/UnitTests/UnitTests.vcxproj b/src/modules/fancyzones/tests/UnitTests/UnitTests.vcxproj index f23f1f7547..80b18ec904 100644 --- a/src/modules/fancyzones/tests/UnitTests/UnitTests.vcxproj +++ b/src/modules/fancyzones/tests/UnitTests/UnitTests.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9} Win32Proj UnitTests - 10.0 + 10.0.17134.0 NativeUnitTestProject UnitTests-FancyZones @@ -131,11 +132,14 @@ + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + \ No newline at end of file diff --git a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp index 96cdf6365b..e0f3ccca09 100644 --- a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp @@ -61,8 +61,8 @@ namespace FancyZonesUnitTests HINSTANCE m_hInst{}; HMONITOR m_monitor{}; MONITORINFO m_monitorInfo{}; - MockZoneWindowHost m_zoneWindowHost{}; - IZoneWindowHost* m_hostPtr = m_zoneWindowHost.get_strong().get(); + winrt::com_ptr m_zoneWindowHost = winrt::make_self(); + IZoneWindowHost* m_hostPtr = m_zoneWindowHost.get(); winrt::com_ptr m_zoneWindow; @@ -391,7 +391,7 @@ namespace FancyZonesUnitTests m_fancyZonesData.SetDeviceInfo(m_parentUniqueId.str(), parentDeviceInfo); auto parentZoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_parentUniqueId.str(), false, false); - m_zoneWindowHost.m_zoneWindow = parentZoneWindow.get(); + m_zoneWindowHost->m_zoneWindow = parentZoneWindow.get(); // newWorkArea = true - zoneWindow will be cloned from parent auto actualZoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, true); @@ -420,7 +420,7 @@ namespace FancyZonesUnitTests m_fancyZonesData.SetDeviceInfo(m_parentUniqueId.str(), parentDeviceInfo); auto parentZoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_parentUniqueId.str(), false, false); - m_zoneWindowHost.m_zoneWindow = parentZoneWindow.get(); + m_zoneWindowHost->m_zoneWindow = parentZoneWindow.get(); // newWorkArea = false - zoneWindow won't be cloned from parent auto actualZoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); diff --git a/src/modules/fancyzones/tests/UnitTests/packages.config b/src/modules/fancyzones/tests/UnitTests/packages.config index 4f733475e9..0e9399589b 100644 --- a/src/modules/fancyzones/tests/UnitTests/packages.config +++ b/src/modules/fancyzones/tests/UnitTests/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/src/modules/fancyzones/tests/UnitTests/pch.h b/src/modules/fancyzones/tests/UnitTests/pch.h index fafb9acece..76b8934733 100644 --- a/src/modules/fancyzones/tests/UnitTests/pch.h +++ b/src/modules/fancyzones/tests/UnitTests/pch.h @@ -9,9 +9,10 @@ // add headers that you want to pre-compile here #include -#include - -#include "lib\pch.h" +#include +#include +#include +#include "lib/pch.h" #include "CppUnitTest.h" #endif //PCH_H diff --git a/src/modules/imageresizer/dll/ContextMenuHandler.cpp b/src/modules/imageresizer/dll/ContextMenuHandler.cpp index b10cdfb91c..b40286faad 100644 --- a/src/modules/imageresizer/dll/ContextMenuHandler.cpp +++ b/src/modules/imageresizer/dll/ContextMenuHandler.cpp @@ -1,6 +1,6 @@ // ContextMenuHandler.cpp : Implementation of CContextMenuHandler -#include "stdafx.h" +#include "pch.h" #include "ContextMenuHandler.h" #include "HDropIterator.h" #include "Settings.h" @@ -37,7 +37,7 @@ HRESULT CContextMenuHandler::Initialize(_In_opt_ PCIDLIST_ABSOLUTE pidlFolder, _ { Uninitialize(); - if (!CSettings::GetEnabled()) + if (!CSettingsInstance().GetEnabled()) { return E_FAIL; } @@ -62,7 +62,7 @@ HRESULT CContextMenuHandler::QueryContextMenu(_In_ HMENU hmenu, UINT indexMenu, { return S_OK; } - if (!CSettings::GetEnabled()) + if (!CSettingsInstance().GetEnabled()) { return E_FAIL; } @@ -354,7 +354,7 @@ HRESULT __stdcall CContextMenuHandler::GetCanonicalName(GUID* pguidCommandName) HRESULT __stdcall CContextMenuHandler::GetState(IShellItemArray* psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE* pCmdState) { - if (!CSettings::GetEnabled()) + if (!CSettingsInstance().GetEnabled()) { *pCmdState = ECS_HIDDEN; return S_OK; diff --git a/src/modules/imageresizer/dll/ContextMenuHandler.h b/src/modules/imageresizer/dll/ContextMenuHandler.h index 975ef17497..256d48a411 100644 --- a/src/modules/imageresizer/dll/ContextMenuHandler.h +++ b/src/modules/imageresizer/dll/ContextMenuHandler.h @@ -2,7 +2,7 @@ #define ID_RESIZE_PICTURES 0 #define RESIZE_PICTURES_VERBW L"resize" -#include "stdafx.h" +#include "pch.h" #include "resource.h" #include "ImageResizerExt_i.h" diff --git a/src/modules/imageresizer/dll/HDropIterator.cpp b/src/modules/imageresizer/dll/HDropIterator.cpp index dad26d2877..bfc23b39ee 100644 --- a/src/modules/imageresizer/dll/HDropIterator.cpp +++ b/src/modules/imageresizer/dll/HDropIterator.cpp @@ -1,4 +1,4 @@ -#include "StdAfx.h" +#include "pch.h" #include "HDropIterator.h" HDropIterator::HDropIterator(IDataObject* pdtobj) diff --git a/src/modules/imageresizer/dll/ImageResizerExt.cpp b/src/modules/imageresizer/dll/ImageResizerExt.cpp index 72ddebe8ca..2999fd4876 100644 --- a/src/modules/imageresizer/dll/ImageResizerExt.cpp +++ b/src/modules/imageresizer/dll/ImageResizerExt.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "resource.h" #include "ImageResizerExt_i.h" #include "dllmain.h" diff --git a/src/modules/imageresizer/dll/ImageResizerExt.vcxproj b/src/modules/imageresizer/dll/ImageResizerExt.vcxproj index eda2904b29..a500b2c7ce 100644 --- a/src/modules/imageresizer/dll/ImageResizerExt.vcxproj +++ b/src/modules/imageresizer/dll/ImageResizerExt.vcxproj @@ -1,5 +1,6 @@  + Debug @@ -20,8 +21,9 @@ {0B43679E-EDFA-4DA0-AD30-F4628B308B1B} - 10.0 + 10.0.17134.0 AtlProj + false @@ -269,7 +271,7 @@ - + Create Create Create @@ -284,7 +286,7 @@ - + @@ -295,6 +297,7 @@ + @@ -309,5 +312,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/imageresizer/dll/ImageResizerExt.vcxproj.filters b/src/modules/imageresizer/dll/ImageResizerExt.vcxproj.filters index b88c6f562e..dc2723e5b8 100644 --- a/src/modules/imageresizer/dll/ImageResizerExt.vcxproj.filters +++ b/src/modules/imageresizer/dll/ImageResizerExt.vcxproj.filters @@ -19,18 +19,12 @@ - - Source Files - Source Files Source Files - - Generated Files - Source Files @@ -46,11 +40,14 @@ Header Files + + Generated Files + + + Source Files + - - Header Files - Header Files @@ -60,9 +57,6 @@ Header Files - - Generated Files - Header Files @@ -72,6 +66,12 @@ Header Files + + Header Files + + + Header Files + @@ -88,15 +88,16 @@ Resource Files - - - - Source Files - + Resource Files + + + Source Files + + \ No newline at end of file diff --git a/src/modules/imageresizer/dll/Settings.cpp b/src/modules/imageresizer/dll/Settings.cpp index f8b446c43d..bdfcc91aa9 100644 --- a/src/modules/imageresizer/dll/Settings.cpp +++ b/src/modules/imageresizer/dll/Settings.cpp @@ -1,66 +1,116 @@ -#include "stdafx.h" -#include +#include "pch.h" #include "Settings.h" -const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\ImageResizer"; -const wchar_t c_enabled[] = L"Enabled"; -const bool c_enabledDefault = true; +#include +#include +#include +#include -bool CSettings::GetEnabled() +namespace { - return GetRegBoolValue(c_enabled, c_enabledDefault); -} + const wchar_t c_imageResizerDataFilePath[] = L"\\image-resizer-settings.json"; + const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\ImageResizer"; + const wchar_t c_enabled[] = L"Enabled"; -bool CSettings::SetEnabled(_In_ bool enabled) -{ - return SetRegBoolValue(c_enabled, enabled); -} - -bool CSettings::SetRegBoolValue(_In_ PCWSTR valueName, _In_ bool value) -{ - DWORD dwValue = value ? 1 : 0; - return SetRegDWORDValue(valueName, dwValue); -} - -bool CSettings::GetRegBoolValue(_In_ PCWSTR valueName, _In_ bool defaultValue) -{ - DWORD value = GetRegDWORDValue(valueName, (defaultValue == 0) ? false : true); - return (value == 0) ? false : true; -} - -bool CSettings::SetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD value) -{ - return (SUCCEEDED(HRESULT_FROM_WIN32(SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, REG_DWORD, &value, sizeof(value))))); -} - -DWORD CSettings::GetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD defaultValue) -{ - DWORD retVal = defaultValue; - DWORD type = REG_DWORD; - DWORD dwEnabled = 0; - DWORD cb = sizeof(dwEnabled); - if (SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, &type, &dwEnabled, &cb) == ERROR_SUCCESS) + unsigned int RegReadInteger(const std::wstring& valueName, unsigned int defaultValue) { - retVal = dwEnabled; + DWORD type = REG_DWORD; + DWORD data = 0; + DWORD size = sizeof(DWORD); + if (SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), &type, &data, &size) == ERROR_SUCCESS) + { + return data; + } + return defaultValue; } - return retVal; -} - -bool CSettings::SetRegStringValue(_In_ PCWSTR valueName, _In_ PCWSTR value) -{ - ULONG cb = (DWORD)((wcslen(value) + 1) * sizeof(*value)); - return (SUCCEEDED(HRESULT_FROM_WIN32(SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, REG_SZ, (const BYTE*)value, cb)))); -} - -bool CSettings::GetRegStringValue(_In_ PCWSTR valueName, __out_ecount(cchBuf) PWSTR value, DWORD cchBuf) -{ - if (cchBuf > 0) + bool RegReadBoolean(const std::wstring& valueName, bool defaultValue) { - value[0] = L'\0'; + DWORD value = RegReadInteger(valueName.c_str(), defaultValue ? 1 : 0); + return (value == 0) ? false : true; } - DWORD type = REG_SZ; - ULONG cb = cchBuf * sizeof(*value); - return (SUCCEEDED(HRESULT_FROM_WIN32(SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, &type, value, &cb) == ERROR_SUCCESS))); + bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime) + { + WIN32_FILE_ATTRIBUTE_DATA attr{}; + if (GetFileAttributesExW(filePath.c_str(), GetFileExInfoStandard, &attr)) + { + *lpFileTime = attr.ftLastWriteTime; + return true; + } + return false; + } +} + +CSettings::CSettings() +{ + std::wstring result = PTSettingsHelper::get_module_save_folder_location(L"ImageResizer"); + jsonFilePath = result + std::wstring(c_imageResizerDataFilePath); + Load(); +} + +void CSettings::Save() +{ + json::JsonObject jsonData; + + jsonData.SetNamedValue(c_enabled, json::value(settings.enabled)); + + json::to_file(jsonFilePath, jsonData); + GetSystemTimeAsFileTime(&lastLoadedTime); +} + +void CSettings::Load() +{ + if (!std::filesystem::exists(jsonFilePath)) + { + MigrateFromRegistry(); + + Save(); + } + else + { + ParseJson(); + } +} + +void CSettings::Reload() +{ + // Load json settings from data file if it is modified in the meantime. + FILETIME lastModifiedTime{}; + if (LastModifiedTime(jsonFilePath, &lastModifiedTime) && + CompareFileTime(&lastModifiedTime, &lastLoadedTime) == 1) + { + Load(); + } +} + +void CSettings::MigrateFromRegistry() +{ + settings.enabled = RegReadBoolean(c_enabled, true); +} + +void CSettings::ParseJson() +{ + auto json = json::from_file(jsonFilePath); + if (json) + { + const json::JsonObject& jsonSettings = json.value(); + try + { + if (json::has(jsonSettings, c_enabled, json::JsonValueType::Boolean)) + { + settings.enabled = jsonSettings.GetNamedBoolean(c_enabled); + } + } + catch (const winrt::hresult_error&) + { + } + } + GetSystemTimeAsFileTime(&lastLoadedTime); +} + +CSettings& CSettingsInstance() +{ + static CSettings instance; + return instance; } \ No newline at end of file diff --git a/src/modules/imageresizer/dll/Settings.h b/src/modules/imageresizer/dll/Settings.h index aa00f9b30d..f0b51861df 100644 --- a/src/modules/imageresizer/dll/Settings.h +++ b/src/modules/imageresizer/dll/Settings.h @@ -3,14 +3,36 @@ class CSettings { public: - static bool GetEnabled(); - static bool SetEnabled(_In_ bool enabled); + CSettings(); + + inline bool GetEnabled() + { + Reload(); + return settings.enabled; + } + + inline void SetEnabled(bool enabled) + { + settings.enabled = enabled; + Save(); + } + + void Save(); + void Load(); private: - static bool GetRegBoolValue(_In_ PCWSTR valueName, _In_ bool defaultValue); - static bool SetRegBoolValue(_In_ PCWSTR valueName, _In_ bool value); - static bool SetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD value); - static DWORD GetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD defaultValue); - static bool SetRegStringValue(_In_ PCWSTR valueName, _In_ PCWSTR value); - static bool GetRegStringValue(_In_ PCWSTR valueName, __out_ecount(cchBuf) PWSTR value, DWORD cchBuf); -}; \ No newline at end of file + struct Settings + { + bool enabled{ true }; + }; + + void Reload(); + void MigrateFromRegistry(); + void ParseJson(); + + Settings settings; + std::wstring jsonFilePath; + FILETIME lastLoadedTime; +}; + +CSettings& CSettingsInstance(); \ No newline at end of file diff --git a/src/modules/imageresizer/dll/dllmain.cpp b/src/modules/imageresizer/dll/dllmain.cpp index b6d7adf630..337fdf4172 100644 --- a/src/modules/imageresizer/dll/dllmain.cpp +++ b/src/modules/imageresizer/dll/dllmain.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "resource.h" #include "ImageResizerExt_i.h" #include "dllmain.h" @@ -37,7 +37,7 @@ public: // Constructor ImageResizerModule() { - m_enabled = CSettings::GetEnabled(); + m_enabled = CSettingsInstance().GetEnabled(); app_name = GET_RESOURCE_STRING(IDS_IMAGERESIZER); }; @@ -87,7 +87,7 @@ public: virtual void enable() { m_enabled = true; - CSettings::SetEnabled(m_enabled); + CSettingsInstance().SetEnabled(m_enabled); Trace::EnableImageResizer(m_enabled); } @@ -95,7 +95,7 @@ public: virtual void disable() { m_enabled = false; - CSettings::SetEnabled(m_enabled); + CSettingsInstance().SetEnabled(m_enabled); Trace::EnableImageResizer(m_enabled); } diff --git a/src/modules/imageresizer/dll/packages.config b/src/modules/imageresizer/dll/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/imageresizer/dll/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/imageresizer/dll/stdafx.cpp b/src/modules/imageresizer/dll/pch.cpp similarity index 62% rename from src/modules/imageresizer/dll/stdafx.cpp rename to src/modules/imageresizer/dll/pch.cpp index a8b5e27d40..a83d3bb2cc 100644 --- a/src/modules/imageresizer/dll/stdafx.cpp +++ b/src/modules/imageresizer/dll/pch.cpp @@ -1,2 +1,2 @@ -#include "stdafx.h" +#include "pch.h" #pragma comment(lib, "windowsapp") \ No newline at end of file diff --git a/src/modules/imageresizer/dll/stdafx.h b/src/modules/imageresizer/dll/pch.h similarity index 83% rename from src/modules/imageresizer/dll/stdafx.h rename to src/modules/imageresizer/dll/pch.h index 5d108dd86e..32d2b50dc3 100644 --- a/src/modules/imageresizer/dll/stdafx.h +++ b/src/modules/imageresizer/dll/pch.h @@ -13,6 +13,8 @@ #include "resource.h" #include +#include +#include #include #include #include diff --git a/src/modules/imageresizer/dll/trace.cpp b/src/modules/imageresizer/dll/trace.cpp index 8bf2d84280..84171932d0 100644 --- a/src/modules/imageresizer/dll/trace.cpp +++ b/src/modules/imageresizer/dll/trace.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "trace.h" TRACELOGGING_DEFINE_PROVIDER( diff --git a/src/modules/imageresizer/ui/App.xaml b/src/modules/imageresizer/ui/App.xaml index 0f47c91079..22503f2c11 100644 --- a/src/modules/imageresizer/ui/App.xaml +++ b/src/modules/imageresizer/ui/App.xaml @@ -27,6 +27,9 @@ + diff --git a/src/modules/imageresizer/ui/Views/AdvancedWindow.xaml b/src/modules/imageresizer/ui/Views/AdvancedWindow.xaml index a76f3b4d8c..d64509f537 100644 --- a/src/modules/imageresizer/ui/Views/AdvancedWindow.xaml +++ b/src/modules/imageresizer/ui/Views/AdvancedWindow.xaml @@ -113,7 +113,7 @@ - + diff --git a/src/modules/imageresizer/ui/Views/InputPage.xaml b/src/modules/imageresizer/ui/Views/InputPage.xaml index 20f45ce831..6130c91719 100644 --- a/src/modules/imageresizer/ui/Views/InputPage.xaml +++ b/src/modules/imageresizer/ui/Views/InputPage.xaml @@ -24,6 +24,7 @@ diff --git a/src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj b/src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj index b578b9c6b9..2101d356a2 100644 --- a/src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj +++ b/src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {e364f67b-bb12-4e91-b639-355866ebcd8b} Win32Proj Wox_Launcher - 10.0 + 10.0.17134.0 Microsoft.Launcher @@ -59,7 +60,6 @@ Disabled true _DEBUG;EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h ..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;..\..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) MultiThreadedDebug @@ -80,7 +80,6 @@ true true NDEBUG;EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h ..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;..\..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) MultiThreaded @@ -117,7 +116,18 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/launcher/Microsoft.Launcher/packages.config b/src/modules/launcher/Microsoft.Launcher/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/launcher/Microsoft.Launcher/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/launcher/Microsoft.Launcher/pch.h b/src/modules/launcher/Microsoft.Launcher/pch.h index 8cb4314b9c..2a7f677299 100644 --- a/src/modules/launcher/Microsoft.Launcher/pch.h +++ b/src/modules/launcher/Microsoft.Launcher/pch.h @@ -1,6 +1,8 @@ #pragma once #define WIN32_LEAN_AND_MEAN #include +#include +#include #include #include #include diff --git a/src/modules/powerrename/UWPui/PowerRenameUWPUI.cpp b/src/modules/powerrename/UWPui/PowerRenameUWPUI.cpp index 8ced4e21b7..a3a9468d31 100644 --- a/src/modules/powerrename/UWPui/PowerRenameUWPUI.cpp +++ b/src/modules/powerrename/UWPui/PowerRenameUWPUI.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "resource.h" #include diff --git a/src/modules/powerrename/UWPui/PowerRenameUWPUI.vcxproj b/src/modules/powerrename/UWPui/PowerRenameUWPUI.vcxproj index aebc0a5aee..63c22a9d8d 100644 --- a/src/modules/powerrename/UWPui/PowerRenameUWPUI.vcxproj +++ b/src/modules/powerrename/UWPui/PowerRenameUWPUI.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {0485F45C-EA7A-4BB5-804B-3E8D14699387} Win32Proj PowerRenameUWPUI - 10.0 + 10.0.17134.0 @@ -45,13 +46,11 @@ false - ..\lib\;..\ui\;..\dll\;$(VC_IncludePath);$(WindowsSDK_IncludePath); $(SolutionDir)$(Platform)\$(Configuration)\modules\ $(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\ true - ..\lib\;..\ui\;..\dll\;$(VC_IncludePath);$(WindowsSDK_IncludePath); $(SolutionDir)$(Platform)\$(Configuration)\modules\ $(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\ @@ -65,7 +64,7 @@ NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false stdcpplatest - ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ + $(ProjectDir)..\;$(ProjectDir)..\ui;$(ProjectDir)..\dll;$(ProjectDir)..\lib;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\common\Telemetry;%(AdditionalIncludeDirectories);$(GeneratedFilesDir) MultiThreaded @@ -75,6 +74,9 @@ true WindowsApp.lib;Comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shcore.lib;%(AdditionalDependencies) + + $(ProjectDir)..\ui;%(AdditionalIncludeDirectories) + @@ -84,24 +86,27 @@ _DEBUG;_WINDOWS;%(PreprocessorDefinitions) false stdcpplatest - ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ MultiThreadedDebug + $(ProjectDir)..\;$(ProjectDir)..\ui;$(ProjectDir)..\dll;$(ProjectDir)..\lib;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\common\Telemetry;%(AdditionalIncludeDirectories);$(GeneratedFilesDir) Windows true WindowsApp.lib;Comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shcore.lib;%(AdditionalDependencies) + + $(ProjectDir)..\ui;%(AdditionalIncludeDirectories) + - + - + Create Create @@ -123,7 +128,18 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/powerrename/UWPui/PowerRenameUWPUI.vcxproj.filters b/src/modules/powerrename/UWPui/PowerRenameUWPUI.vcxproj.filters index ea6394725d..9914abe928 100644 --- a/src/modules/powerrename/UWPui/PowerRenameUWPUI.vcxproj.filters +++ b/src/modules/powerrename/UWPui/PowerRenameUWPUI.vcxproj.filters @@ -18,10 +18,10 @@ Header Files - + Header Files - + Header Files @@ -29,10 +29,10 @@ Source Files - + Source Files - + Source Files @@ -46,4 +46,7 @@ Resource Files + + + \ No newline at end of file diff --git a/src/modules/powerrename/UWPui/packages.config b/src/modules/powerrename/UWPui/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/powerrename/UWPui/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/powerrename/UWPui/pch.cpp b/src/modules/powerrename/UWPui/pch.cpp new file mode 100644 index 0000000000..1d9f38c57d --- /dev/null +++ b/src/modules/powerrename/UWPui/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/src/modules/powerrename/UWPui/stdafx.h b/src/modules/powerrename/UWPui/pch.h similarity index 75% rename from src/modules/powerrename/UWPui/stdafx.h rename to src/modules/powerrename/UWPui/pch.h index ecc0767b50..50c1a6eb8f 100644 --- a/src/modules/powerrename/UWPui/stdafx.h +++ b/src/modules/powerrename/UWPui/pch.h @@ -1,7 +1,6 @@ #pragma once #include "targetver.h" - #include -#include #include +#include "winrt/base.h" \ No newline at end of file diff --git a/src/modules/powerrename/UWPui/stdafx.cpp b/src/modules/powerrename/UWPui/stdafx.cpp deleted file mode 100644 index fd4f341c7b..0000000000 --- a/src/modules/powerrename/UWPui/stdafx.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "stdafx.h" diff --git a/src/modules/powerrename/dll/PowerRenameExt.cpp b/src/modules/powerrename/dll/PowerRenameExt.cpp index 3004a14feb..b1fa1305c4 100644 --- a/src/modules/powerrename/dll/PowerRenameExt.cpp +++ b/src/modules/powerrename/dll/PowerRenameExt.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "PowerRenameExt.h" #include #include diff --git a/src/modules/powerrename/dll/PowerRenameExt.h b/src/modules/powerrename/dll/PowerRenameExt.h index 01906d14ab..ab575ab1d4 100644 --- a/src/modules/powerrename/dll/PowerRenameExt.h +++ b/src/modules/powerrename/dll/PowerRenameExt.h @@ -1,5 +1,5 @@ #pragma once -#include "stdafx.h" +#include "pch.h" class __declspec(uuid("0440049F-D1DC-4E46-B27B-98393D79486B")) CPowerRenameMenu : public IShellExtInit, diff --git a/src/modules/powerrename/dll/PowerRenameExt.vcxproj b/src/modules/powerrename/dll/PowerRenameExt.vcxproj index 152bbeba49..1bc1280159 100644 --- a/src/modules/powerrename/dll/PowerRenameExt.vcxproj +++ b/src/modules/powerrename/dll/PowerRenameExt.vcxproj @@ -1,5 +1,6 @@  + Debug @@ -22,7 +23,7 @@ 15.0 {B25AC7A5-FB9F-4789-B392-D5C85E948670} PowerRenameExt - 10.0 + 10.0.17134.0 @@ -101,7 +102,6 @@ Level3 Disabled true - true stdcpp17 MultiThreadedDebug ..\;..\..\..\common;..\..\..\common\telemetry;..\..\;%(AdditionalIncludeDirectories) @@ -116,7 +116,6 @@ Level3 Disabled true - true stdcpplatest MultiThreadedDebug ..\;..\..\..\common;..\..\..\common\telemetry;..\..\;..\..\..\;..\..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) @@ -133,7 +132,6 @@ true true true - true stdcpp17 MultiThreaded ..\;..\..\..\common;..\..\..\common\telemetry;..\..\;%(AdditionalIncludeDirectories) @@ -152,7 +150,6 @@ true true true - true stdcpplatest MultiThreaded ..\;..\..\..\common;..\..\..\common\telemetry;..\..\;..\..\..\;..\..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) @@ -169,7 +166,7 @@ - + @@ -178,9 +175,10 @@ - + + @@ -196,5 +194,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/powerrename/dll/PowerRenameExt.vcxproj.filters b/src/modules/powerrename/dll/PowerRenameExt.vcxproj.filters index d4744b4b1a..a8b06ef642 100644 --- a/src/modules/powerrename/dll/PowerRenameExt.vcxproj.filters +++ b/src/modules/powerrename/dll/PowerRenameExt.vcxproj.filters @@ -15,9 +15,6 @@ - - Header Files - Header Files @@ -30,6 +27,9 @@ Header Files + + Header Files + @@ -43,7 +43,7 @@ Source Files - + Source Files @@ -51,5 +51,6 @@ Source Files + \ No newline at end of file diff --git a/src/modules/powerrename/dll/dllmain.cpp b/src/modules/powerrename/dll/dllmain.cpp index 2629137635..da684cc0a4 100644 --- a/src/modules/powerrename/dll/dllmain.cpp +++ b/src/modules/powerrename/dll/dllmain.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "PowerRenameExt.h" #include #include diff --git a/src/modules/powerrename/dll/packages.config b/src/modules/powerrename/dll/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/powerrename/dll/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/powerrename/dll/stdafx.cpp b/src/modules/powerrename/dll/pch.cpp similarity index 63% rename from src/modules/powerrename/dll/stdafx.cpp rename to src/modules/powerrename/dll/pch.cpp index 76d63011b5..58894606d4 100644 --- a/src/modules/powerrename/dll/stdafx.cpp +++ b/src/modules/powerrename/dll/pch.cpp @@ -1,2 +1,2 @@ -#include "stdafx.h" +#include "pch.h" #pragma comment(lib, "windowsapp") diff --git a/src/modules/powerrename/dll/stdafx.h b/src/modules/powerrename/dll/pch.h similarity index 78% rename from src/modules/powerrename/dll/stdafx.h rename to src/modules/powerrename/dll/pch.h index 11511d3aa0..f3036a15a2 100644 --- a/src/modules/powerrename/dll/stdafx.h +++ b/src/modules/powerrename/dll/pch.h @@ -4,7 +4,8 @@ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files: -#include +#include +#include #include #include #include diff --git a/src/modules/powerrename/lib/Helpers.cpp b/src/modules/powerrename/lib/Helpers.cpp index 0fc92577a5..def7bdd97c 100644 --- a/src/modules/powerrename/lib/Helpers.cpp +++ b/src/modules/powerrename/lib/Helpers.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "Helpers.h" #include diff --git a/src/modules/powerrename/lib/PowerRenameInterfaces.h b/src/modules/powerrename/lib/PowerRenameInterfaces.h index dad2919dc6..b87201cc71 100644 --- a/src/modules/powerrename/lib/PowerRenameInterfaces.h +++ b/src/modules/powerrename/lib/PowerRenameInterfaces.h @@ -1,5 +1,5 @@ #pragma once -#include "stdafx.h" +#include "pch.h" enum PowerRenameFlags { diff --git a/src/modules/powerrename/lib/PowerRenameItem.cpp b/src/modules/powerrename/lib/PowerRenameItem.cpp index 83aded4c2b..642baab256 100644 --- a/src/modules/powerrename/lib/PowerRenameItem.cpp +++ b/src/modules/powerrename/lib/PowerRenameItem.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "PowerRenameItem.h" #include "icon_helpers.h" diff --git a/src/modules/powerrename/lib/PowerRenameItem.h b/src/modules/powerrename/lib/PowerRenameItem.h index 27be6a55f3..9fb1874ccb 100644 --- a/src/modules/powerrename/lib/PowerRenameItem.h +++ b/src/modules/powerrename/lib/PowerRenameItem.h @@ -1,5 +1,5 @@ #pragma once -#include "stdafx.h" +#include "pch.h" #include "PowerRenameInterfaces.h" #include "srwlock.h" diff --git a/src/modules/powerrename/lib/PowerRenameLib.vcxproj b/src/modules/powerrename/lib/PowerRenameLib.vcxproj index 6bc9faabbd..14415515b9 100644 --- a/src/modules/powerrename/lib/PowerRenameLib.vcxproj +++ b/src/modules/powerrename/lib/PowerRenameLib.vcxproj @@ -1,5 +1,6 @@  + Debug @@ -22,7 +23,7 @@ {51920F1F-C28C-4ADF-8660-4238766796C2} Win32Proj PowerRenameLib - 10.0 + 10.0.17134.0 @@ -92,7 +93,7 @@ true stdcpp17 MultiThreadedDebug - stdafx.h + pch.h Windows @@ -107,8 +108,8 @@ true stdcpp17 MultiThreadedDebug - ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ - stdafx.h + $(ProjectDir)..\;$(ProjectDir)..\ui;$(ProjectDir)..\dll;$(ProjectDir)..\lib;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\common\Telemetry;%(AdditionalIncludeDirectories);$(GeneratedFilesDir) + pch.h Windows @@ -126,7 +127,7 @@ true stdcpp17 MultiThreaded - stdafx.h + pch.h Windows @@ -145,8 +146,8 @@ true stdcpp17 MultiThreaded - ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ - stdafx.h + $(ProjectDir)..\;$(ProjectDir)..\ui;$(ProjectDir)..\dll;$(ProjectDir)..\lib;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\common\Telemetry;%(AdditionalIncludeDirectories);$(GeneratedFilesDir) + pch.h Windows @@ -163,7 +164,7 @@ - + @@ -173,7 +174,7 @@ - + Create Create Create @@ -181,7 +182,18 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/powerrename/lib/PowerRenameManager.cpp b/src/modules/powerrename/lib/PowerRenameManager.cpp index 046ff3e18a..17b2b186ce 100644 --- a/src/modules/powerrename/lib/PowerRenameManager.cpp +++ b/src/modules/powerrename/lib/PowerRenameManager.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "PowerRenameManager.h" #include "PowerRenameRegEx.h" // Default RegEx handler #include diff --git a/src/modules/powerrename/lib/PowerRenameRegEx.cpp b/src/modules/powerrename/lib/PowerRenameRegEx.cpp index 9da77601e1..3b7b3dee15 100644 --- a/src/modules/powerrename/lib/PowerRenameRegEx.cpp +++ b/src/modules/powerrename/lib/PowerRenameRegEx.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "PowerRenameRegEx.h" #include #include diff --git a/src/modules/powerrename/lib/PowerRenameRegEx.h b/src/modules/powerrename/lib/PowerRenameRegEx.h index a1480bce13..d7a254b246 100644 --- a/src/modules/powerrename/lib/PowerRenameRegEx.h +++ b/src/modules/powerrename/lib/PowerRenameRegEx.h @@ -1,5 +1,5 @@ #pragma once -#include "stdafx.h" +#include "pch.h" #include #include #include "srwlock.h" diff --git a/src/modules/powerrename/lib/Settings.cpp b/src/modules/powerrename/lib/Settings.cpp index a7f20dde0c..9de15f6b68 100644 --- a/src/modules/powerrename/lib/Settings.cpp +++ b/src/modules/powerrename/lib/Settings.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "Settings.h" #include "PowerRenameInterfaces.h" #include "settings_helpers.h" @@ -6,10 +6,12 @@ #include #include #include +#include namespace { const wchar_t c_powerRenameDataFilePath[] = L"\\power-rename-settings.json"; + const wchar_t c_powerRenameUIFlagsFilePath[] = L"\\power-rename-ui-flags"; const wchar_t c_searchMRUListFilePath[] = L"\\search-mru.json"; const wchar_t c_replaceMRUListFilePath[] = L"\\replace-mru.json"; @@ -29,7 +31,7 @@ namespace const wchar_t c_mruList[] = L"MRUList"; const wchar_t c_insertionIdx[] = L"InsertionIdx"; - long GetRegNumber(const std::wstring& valueName, long defaultValue) + unsigned int GetRegNumber(const std::wstring& valueName, unsigned int defaultValue) { DWORD type = REG_DWORD; DWORD data = 0; @@ -41,7 +43,7 @@ namespace return defaultValue; } - void SetRegNumber(const std::wstring& valueName, long value) + void SetRegNumber(const std::wstring& valueName, unsigned int value) { SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), REG_DWORD, &value, sizeof(value)); } @@ -86,7 +88,7 @@ namespace class MRUListHandler { public: - MRUListHandler(int size, const std::wstring& filePath, const std::wstring& regPath) : + MRUListHandler(unsigned int size, const std::wstring& filePath, const std::wstring& regPath) : pushIdx(0), nextIdx(1), size(size), @@ -112,9 +114,9 @@ private: bool Exists(const std::wstring& data); std::vector items; - long pushIdx; - long nextIdx; - long size; + unsigned int pushIdx; + unsigned int nextIdx; + unsigned int size; const std::wstring jsonFilePath; const std::wstring registryFilePath; }; @@ -140,7 +142,7 @@ bool MRUListHandler::Next(std::wstring& data) return false; } // Go backwards to consume latest items first. - long idx = (pushIdx + size - nextIdx) % size; + unsigned int idx = (pushIdx + size - nextIdx) % size; if (items[idx].empty()) { Reset(); @@ -212,15 +214,15 @@ void MRUListHandler::ParseJson() const json::JsonObject& jsonObject = json.value(); try { - long oldSize{ size }; + unsigned int oldSize{ size }; if (json::has(jsonObject, c_maxMRUSize, json::JsonValueType::Number)) { - oldSize = (long)jsonObject.GetNamedNumber(c_maxMRUSize); + oldSize = (unsigned int)jsonObject.GetNamedNumber(c_maxMRUSize); } - long oldPushIdx{ 0 }; + unsigned int oldPushIdx{ 0 }; if (json::has(jsonObject, c_insertionIdx, json::JsonValueType::Number)) { - oldPushIdx = (long)jsonObject.GetNamedNumber(c_insertionIdx); + oldPushIdx = (unsigned int)jsonObject.GetNamedNumber(c_insertionIdx); if (oldPushIdx < 0 || oldPushIdx >= oldSize) { oldPushIdx = 0; @@ -240,7 +242,7 @@ void MRUListHandler::ParseJson() else { std::vector temp; - for (uint32_t i = 0; i < min(jsonArray.Size(), size); ++i) + for (unsigned int i = 0; i < min(jsonArray.Size(), size); ++i) { int idx = (oldPushIdx + oldSize - (i + 1)) % oldSize; temp.push_back(std::wstring(jsonArray.GetStringAt(idx))); @@ -248,7 +250,7 @@ void MRUListHandler::ParseJson() if (size > oldSize) { std::reverse(std::begin(temp), std::end(temp)); - pushIdx = (long)temp.size(); + pushIdx = (unsigned int)temp.size(); temp.resize(size); } else @@ -295,7 +297,7 @@ private: CRenameMRU(int size, const std::wstring& filePath, const std::wstring& regPath); std::unique_ptr mruList; - long refCount = 0; + unsigned int refCount = 0; }; CRenameMRU::CRenameMRU(int size, const std::wstring& filePath, const std::wstring& regPath) : @@ -307,7 +309,7 @@ CRenameMRU::CRenameMRU(int size, const std::wstring& filePath, const std::wstrin HRESULT CRenameMRU::CreateInstance(_In_ const std::wstring& filePath, _In_ const std::wstring& regPath, _Outptr_ IUnknown** ppUnk) { *ppUnk = nullptr; - long maxMRUSize = CSettingsInstance().GetMaxMRUSize(); + unsigned int maxMRUSize = CSettingsInstance().GetMaxMRUSize(); HRESULT hr = maxMRUSize > 0 ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { @@ -330,7 +332,7 @@ IFACEMETHODIMP_(ULONG) CRenameMRU::AddRef() IFACEMETHODIMP_(ULONG) CRenameMRU::Release() { - long cnt = InterlockedDecrement(&refCount); + unsigned int cnt = InterlockedDecrement(&refCount); if (cnt == 0) { @@ -395,6 +397,7 @@ CSettings::CSettings() { std::wstring result = PTSettingsHelper::get_module_save_folder_location(L"PowerRename"); jsonFilePath = result + std::wstring(c_powerRenameDataFilePath); + UIFlagsFilePath = result + std::wstring(c_powerRenameUIFlagsFilePath); Load(); } @@ -408,11 +411,11 @@ void CSettings::Save() jsonData.SetNamedValue(c_persistState, json::value(settings.persistState)); jsonData.SetNamedValue(c_mruEnabled, json::value(settings.MRUEnabled)); jsonData.SetNamedValue(c_maxMRUSize, json::value(settings.maxMRUSize)); - jsonData.SetNamedValue(c_flags, json::value(settings.flags)); jsonData.SetNamedValue(c_searchText, json::value(settings.searchText)); jsonData.SetNamedValue(c_replaceText, json::value(settings.replaceText)); json::to_file(jsonFilePath, jsonData); + GetSystemTimeAsFileTime(&lastLoadedTime); } void CSettings::Load() @@ -422,12 +425,13 @@ void CSettings::Load() MigrateFromRegistry(); Save(); + WriteFlags(); } else { ParseJson(); + ReadFlags(); } - GetSystemTimeAsFileTime(&lastLoadedTime); } void CSettings::Reload() @@ -441,7 +445,6 @@ void CSettings::Reload() } } - void CSettings::MigrateFromRegistry() { settings.enabled = GetRegBoolean(c_enabled, true); @@ -485,11 +488,7 @@ void CSettings::ParseJson() } if (json::has(jsonSettings, c_maxMRUSize, json::JsonValueType::Number)) { - settings.maxMRUSize = (long)jsonSettings.GetNamedNumber(c_maxMRUSize); - } - if (json::has(jsonSettings, c_flags, json::JsonValueType::Number)) - { - settings.flags = (long)jsonSettings.GetNamedNumber(c_flags); + settings.maxMRUSize = (unsigned int)jsonSettings.GetNamedNumber(c_maxMRUSize); } if (json::has(jsonSettings, c_searchText, json::JsonValueType::String)) { @@ -502,6 +501,25 @@ void CSettings::ParseJson() } catch (const winrt::hresult_error&) { } } + GetSystemTimeAsFileTime(&lastLoadedTime); +} + +void CSettings::ReadFlags() +{ + std::ifstream file(UIFlagsFilePath, std::ios::binary); + if (file.is_open()) + { + file >> settings.flags; + } +} + +void CSettings::WriteFlags() +{ + std::ofstream file(UIFlagsFilePath, std::ios::binary); + if (file.is_open()) + { + file << settings.flags; + } } CSettings& CSettingsInstance() diff --git a/src/modules/powerrename/lib/Settings.h b/src/modules/powerrename/lib/Settings.h index e82c5c0b65..f91ad4c9ec 100644 --- a/src/modules/powerrename/lib/Settings.h +++ b/src/modules/powerrename/lib/Settings.h @@ -61,25 +61,25 @@ public: settings.MRUEnabled = MRUEnabled; } - inline long GetMaxMRUSize() const + inline unsigned int GetMaxMRUSize() const { return settings.maxMRUSize; } - inline void SetMaxMRUSize(long maxMRUSize) + inline void SetMaxMRUSize(unsigned int maxMRUSize) { settings.maxMRUSize = maxMRUSize; } - inline long GetFlags() const + inline unsigned int GetFlags() const { return settings.flags; } - inline void SetFlags(long flags) + inline void SetFlags(unsigned int flags) { settings.flags = flags; - Save(); + WriteFlags(); } inline const std::wstring& GetSearchText() const @@ -115,8 +115,8 @@ private: bool extendedContextMenuOnly{ false }; // Disabled by default. bool persistState{ true }; bool MRUEnabled{ true }; - long maxMRUSize{ 10 }; - long flags{ 0 }; + unsigned int maxMRUSize{ 10 }; + unsigned int flags{ 0 }; std::wstring searchText{}; std::wstring replaceText{}; }; @@ -125,8 +125,12 @@ private: void MigrateFromRegistry(); void ParseJson(); + void ReadFlags(); + void WriteFlags(); + Settings settings; std::wstring jsonFilePath; + std::wstring UIFlagsFilePath; FILETIME lastLoadedTime; }; diff --git a/src/modules/powerrename/lib/packages.config b/src/modules/powerrename/lib/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/powerrename/lib/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/powerrename/lib/pch.cpp b/src/modules/powerrename/lib/pch.cpp new file mode 100644 index 0000000000..ce9b73991b --- /dev/null +++ b/src/modules/powerrename/lib/pch.cpp @@ -0,0 +1,2 @@ +#include "pch.h" + diff --git a/src/modules/powerrename/lib/stdafx.h b/src/modules/powerrename/lib/pch.h similarity index 100% rename from src/modules/powerrename/lib/stdafx.h rename to src/modules/powerrename/lib/pch.h diff --git a/src/modules/powerrename/lib/srwlock.h b/src/modules/powerrename/lib/srwlock.h index 72f2372e30..d0cd8a5f36 100644 --- a/src/modules/powerrename/lib/srwlock.h +++ b/src/modules/powerrename/lib/srwlock.h @@ -1,5 +1,5 @@ #pragma once -#include "stdafx.h" +#include "pch.h" // Wrapper around SRWLOCK class CSRWLock diff --git a/src/modules/powerrename/lib/stdafx.cpp b/src/modules/powerrename/lib/stdafx.cpp deleted file mode 100644 index 804d0881d3..0000000000 --- a/src/modules/powerrename/lib/stdafx.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "stdafx.h" - diff --git a/src/modules/powerrename/lib/trace.cpp b/src/modules/powerrename/lib/trace.cpp index da2ad630f4..ff539984f0 100644 --- a/src/modules/powerrename/lib/trace.cpp +++ b/src/modules/powerrename/lib/trace.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "trace.h" #include "Settings.h" diff --git a/src/modules/powerrename/testapp/PowerRenameTest.cpp b/src/modules/powerrename/testapp/PowerRenameTest.cpp index 529eb0c2f4..f635ec47b2 100644 --- a/src/modules/powerrename/testapp/PowerRenameTest.cpp +++ b/src/modules/powerrename/testapp/PowerRenameTest.cpp @@ -1,7 +1,7 @@ // PowerRenameTest.cpp : Defines the entry point for the application. // -#include "stdafx.h" +#include "pch.h" #include "PowerRenameTest.h" #include #include diff --git a/src/modules/powerrename/testapp/PowerRenameTest.vcxproj b/src/modules/powerrename/testapp/PowerRenameTest.vcxproj index 7e9252444c..0554cf971f 100644 --- a/src/modules/powerrename/testapp/PowerRenameTest.vcxproj +++ b/src/modules/powerrename/testapp/PowerRenameTest.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -23,7 +24,7 @@ {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2} Win32Proj PowerRenameTest - 10.0 + 10.0.17134.0 @@ -99,7 +100,6 @@ Disabled true WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - true stdcpp17 MultiThreadedDebug @@ -116,10 +116,9 @@ Disabled true _DEBUG;_WINDOWS;%(PreprocessorDefinitions) - true stdcpp17 MultiThreadedDebug - ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ + $(ProjectDir)..\;$(ProjectDir)..\ui;$(ProjectDir)..\dll;$(ProjectDir)..\lib;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\common\Telemetry;%(AdditionalIncludeDirectories);$(GeneratedFilesDir) Windows @@ -136,7 +135,6 @@ true true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - true stdcpp17 MultiThreaded @@ -157,10 +155,9 @@ true true NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - true stdcpp17 MultiThreaded - ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ + $(ProjectDir)..\;$(ProjectDir)..\ui;$(ProjectDir)..\dll;$(ProjectDir)..\lib;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\common\Telemetry;%(AdditionalIncludeDirectories);$(GeneratedFilesDir) Windows @@ -174,12 +171,12 @@ - + - + Create Create Create @@ -194,7 +191,18 @@ {74485049-c722-400f-abe5-86ac52d929b3} + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/powerrename/testapp/PowerRenameTest.vcxproj.filters b/src/modules/powerrename/testapp/PowerRenameTest.vcxproj.filters index c3b11225d1..ef08cb86a3 100644 --- a/src/modules/powerrename/testapp/PowerRenameTest.vcxproj.filters +++ b/src/modules/powerrename/testapp/PowerRenameTest.vcxproj.filters @@ -15,9 +15,6 @@ - - Header Files - Header Files @@ -27,12 +24,15 @@ Header Files + + Header Files + - + Source Files - + Source Files @@ -41,4 +41,7 @@ Resource Files + + + \ No newline at end of file diff --git a/src/modules/powerrename/testapp/packages.config b/src/modules/powerrename/testapp/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/powerrename/testapp/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/powerrename/testapp/pch.cpp b/src/modules/powerrename/testapp/pch.cpp new file mode 100644 index 0000000000..1d9f38c57d --- /dev/null +++ b/src/modules/powerrename/testapp/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/src/modules/powerrename/testapp/stdafx.h b/src/modules/powerrename/testapp/pch.h similarity index 100% rename from src/modules/powerrename/testapp/stdafx.h rename to src/modules/powerrename/testapp/pch.h diff --git a/src/modules/powerrename/testapp/stdafx.cpp b/src/modules/powerrename/testapp/stdafx.cpp deleted file mode 100644 index fd4f341c7b..0000000000 --- a/src/modules/powerrename/testapp/stdafx.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "stdafx.h" diff --git a/src/modules/powerrename/ui/PowerRenameUI.cpp b/src/modules/powerrename/ui/PowerRenameUI.cpp index c4bd0b5eaa..6aa9ab3e15 100644 --- a/src/modules/powerrename/ui/PowerRenameUI.cpp +++ b/src/modules/powerrename/ui/PowerRenameUI.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "resource.h" #include "PowerRenameUI.h" #include "dpi_aware.h" diff --git a/src/modules/powerrename/ui/PowerRenameUI.vcxproj b/src/modules/powerrename/ui/PowerRenameUI.vcxproj index 66a20b1312..683d6e499a 100644 --- a/src/modules/powerrename/ui/PowerRenameUI.vcxproj +++ b/src/modules/powerrename/ui/PowerRenameUI.vcxproj @@ -1,5 +1,6 @@  + Debug @@ -14,7 +15,7 @@ {0E072714-D127-460B-AFAD-B4C40B412798} Win32Proj PowerRename - 10.0 + 10.0.17134.0 PowerRenameUI @@ -98,7 +99,7 @@ true stdcpp17 MultiThreadedDebug - ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ + $(ProjectDir)..\;$(ProjectDir)..\ui;$(ProjectDir)..\dll;$(ProjectDir)..\lib;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\common\Telemetry;%(AdditionalIncludeDirectories);$(GeneratedFilesDir) Windows @@ -136,7 +137,7 @@ true stdcpp17 MultiThreaded - ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ + $(ProjectDir)..\;$(ProjectDir)..\ui;$(ProjectDir)..\dll;$(ProjectDir)..\lib;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\common\Telemetry;%(AdditionalIncludeDirectories);$(GeneratedFilesDir) Windows @@ -154,12 +155,12 @@ - + - + Create Create Create @@ -172,7 +173,18 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/powerrename/ui/packages.config b/src/modules/powerrename/ui/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/powerrename/ui/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/powerrename/ui/pch.cpp b/src/modules/powerrename/ui/pch.cpp new file mode 100644 index 0000000000..17305716aa --- /dev/null +++ b/src/modules/powerrename/ui/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" \ No newline at end of file diff --git a/src/modules/powerrename/ui/stdafx.h b/src/modules/powerrename/ui/pch.h similarity index 100% rename from src/modules/powerrename/ui/stdafx.h rename to src/modules/powerrename/ui/pch.h diff --git a/src/modules/powerrename/ui/stdafx.cpp b/src/modules/powerrename/ui/stdafx.cpp deleted file mode 100644 index 1577c4e3bc..0000000000 --- a/src/modules/powerrename/ui/stdafx.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "stdafx.h" \ No newline at end of file diff --git a/src/modules/powerrename/unittests/MockPowerRenameItem.cpp b/src/modules/powerrename/unittests/MockPowerRenameItem.cpp index d666e5fcc7..9a338d8fca 100644 --- a/src/modules/powerrename/unittests/MockPowerRenameItem.cpp +++ b/src/modules/powerrename/unittests/MockPowerRenameItem.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "MockPowerRenameItem.h" HRESULT CMockPowerRenameItem::CreateInstance(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalName, _In_ UINT depth, _In_ bool isFolder, _Outptr_ IPowerRenameItem** ppItem) diff --git a/src/modules/powerrename/unittests/MockPowerRenameItem.h b/src/modules/powerrename/unittests/MockPowerRenameItem.h index 2b41e4321d..9525a4db7d 100644 --- a/src/modules/powerrename/unittests/MockPowerRenameItem.h +++ b/src/modules/powerrename/unittests/MockPowerRenameItem.h @@ -1,5 +1,5 @@ #pragma once -#include "stdafx.h" +#include "pch.h" #include #include "srwlock.h" diff --git a/src/modules/powerrename/unittests/MockPowerRenameManagerEvents.cpp b/src/modules/powerrename/unittests/MockPowerRenameManagerEvents.cpp index d44dff4e6c..db09e2727d 100644 --- a/src/modules/powerrename/unittests/MockPowerRenameManagerEvents.cpp +++ b/src/modules/powerrename/unittests/MockPowerRenameManagerEvents.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "MockPowerRenameManagerEvents.h" // IUnknown diff --git a/src/modules/powerrename/unittests/MockPowerRenameRegExEvents.cpp b/src/modules/powerrename/unittests/MockPowerRenameRegExEvents.cpp index 273f0a1a27..f76bb4e30b 100644 --- a/src/modules/powerrename/unittests/MockPowerRenameRegExEvents.cpp +++ b/src/modules/powerrename/unittests/MockPowerRenameRegExEvents.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "MockPowerRenameRegExEvents.h" IFACEMETHODIMP_(ULONG) diff --git a/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj b/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj index 795d47a53f..6bb06152dc 100644 --- a/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj +++ b/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj @@ -1,5 +1,6 @@  + Debug @@ -22,7 +23,7 @@ {2151F984-E006-4A9F-92EF-C6DDE3DC8413} Win32Proj PowerRenameLibUnitTests - 10.0 + 10.0.17134.0 PowerRenameUnitTests @@ -178,7 +179,7 @@ - + @@ -187,7 +188,7 @@ - + Create Create Create @@ -201,7 +202,18 @@ {74485049-c722-400f-abe5-86ac52d929b3} + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/powerrename/unittests/PowerRenameManagerTests.cpp b/src/modules/powerrename/unittests/PowerRenameManagerTests.cpp index d096665382..b981e59865 100644 --- a/src/modules/powerrename/unittests/PowerRenameManagerTests.cpp +++ b/src/modules/powerrename/unittests/PowerRenameManagerTests.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "CppUnitTest.h" #include #include diff --git a/src/modules/powerrename/unittests/PowerRenameRegExTests.cpp b/src/modules/powerrename/unittests/PowerRenameRegExTests.cpp index c1cf77ccb0..32668c9d5e 100644 --- a/src/modules/powerrename/unittests/PowerRenameRegExTests.cpp +++ b/src/modules/powerrename/unittests/PowerRenameRegExTests.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "CppUnitTest.h" #include #include diff --git a/src/modules/powerrename/unittests/TestFileHelper.cpp b/src/modules/powerrename/unittests/TestFileHelper.cpp index 5d4d9b0e48..6d55ae0659 100644 --- a/src/modules/powerrename/unittests/TestFileHelper.cpp +++ b/src/modules/powerrename/unittests/TestFileHelper.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "pch.h" #include "TestFileHelper.h" #include #include diff --git a/src/modules/powerrename/unittests/packages.config b/src/modules/powerrename/unittests/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/powerrename/unittests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/powerrename/unittests/pch.cpp b/src/modules/powerrename/unittests/pch.cpp new file mode 100644 index 0000000000..1d9f38c57d --- /dev/null +++ b/src/modules/powerrename/unittests/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/src/modules/powerrename/unittests/stdafx.h b/src/modules/powerrename/unittests/pch.h similarity index 100% rename from src/modules/powerrename/unittests/stdafx.h rename to src/modules/powerrename/unittests/pch.h diff --git a/src/modules/powerrename/unittests/stdafx.cpp b/src/modules/powerrename/unittests/stdafx.cpp deleted file mode 100644 index fd4f341c7b..0000000000 --- a/src/modules/powerrename/unittests/stdafx.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "stdafx.h" diff --git a/src/modules/previewpane/powerpreview/packages.config b/src/modules/previewpane/powerpreview/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/previewpane/powerpreview/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/previewpane/powerpreview/pch.h b/src/modules/previewpane/powerpreview/pch.h index f7efdb5cfe..b3224ba1ab 100644 --- a/src/modules/previewpane/powerpreview/pch.h +++ b/src/modules/previewpane/powerpreview/pch.h @@ -1,5 +1,7 @@ #pragma once #define WIN32_LEAN_AND_MEAN #include +#include +#include #include #include \ No newline at end of file diff --git a/src/modules/previewpane/powerpreview/powerpreview.vcxproj b/src/modules/previewpane/powerpreview/powerpreview.vcxproj index abf0ad47f1..d8ec98a311 100644 --- a/src/modules/previewpane/powerpreview/powerpreview.vcxproj +++ b/src/modules/previewpane/powerpreview/powerpreview.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {217DF501-135C-4E38-BFC8-99D4821032EA} Win32Proj examplepowertoy - 10.0 + 10.0.17134.0 powerpreview @@ -61,7 +62,6 @@ Disabled true _DEBUG;EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h ..\;..\..\..\common;..\..\..\common\telemetry;..\..\;..\..\..\;..\..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) MultiThreadedDebug @@ -83,7 +83,6 @@ true true NDEBUG;EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h ..\..\..\common\Telemetry;..\..\..\common;..\..\common\inc;..\common\Telemetry;..\;..\..\;..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) MultiThreaded @@ -130,9 +129,18 @@ + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/previewpane/powerpreview/powerpreview.vcxproj.filters b/src/modules/previewpane/powerpreview/powerpreview.vcxproj.filters index eff3d1d039..737fddd268 100644 --- a/src/modules/previewpane/powerpreview/powerpreview.vcxproj.filters +++ b/src/modules/previewpane/powerpreview/powerpreview.vcxproj.filters @@ -23,5 +23,6 @@ + \ No newline at end of file diff --git a/src/modules/previewpane/powerpreviewTest/packages.config b/src/modules/previewpane/powerpreviewTest/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/previewpane/powerpreviewTest/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/previewpane/powerpreviewTest/pch.h b/src/modules/previewpane/powerpreviewTest/pch.h index 85bdb7bd5c..7454b1ec11 100644 --- a/src/modules/previewpane/powerpreviewTest/pch.h +++ b/src/modules/previewpane/powerpreviewTest/pch.h @@ -10,6 +10,8 @@ // add headers that you want to pre-compile here #include #include +#include +#include #include "CppUnitTest.h" #endif //PCH_H diff --git a/src/modules/previewpane/powerpreviewTest/powerpreviewTest.vcxproj b/src/modules/previewpane/powerpreviewTest/powerpreviewTest.vcxproj index 3875b90a63..6098cce8e0 100644 --- a/src/modules/previewpane/powerpreviewTest/powerpreviewTest.vcxproj +++ b/src/modules/previewpane/powerpreviewTest/powerpreviewTest.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -23,7 +24,7 @@ {47310AB4-9034-4BD1-8D8B-E88AD21A171B} Win32Proj powerpreviewTest - 10.0 + 10.0.17134.0 NativeUnitTestProject @@ -179,7 +180,18 @@ {74485049-c722-400f-abe5-86ac52d929b3} + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/previewpane/powerpreviewTest/powerpreviewTest.vcxproj.filters b/src/modules/previewpane/powerpreviewTest/powerpreviewTest.vcxproj.filters index 4fc696fd53..0ab423a082 100644 --- a/src/modules/previewpane/powerpreviewTest/powerpreviewTest.vcxproj.filters +++ b/src/modules/previewpane/powerpreviewTest/powerpreviewTest.vcxproj.filters @@ -27,4 +27,7 @@ Header Files + + + \ No newline at end of file diff --git a/src/modules/shortcut_guide/packages.config b/src/modules/shortcut_guide/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/modules/shortcut_guide/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/shortcut_guide/pch.h b/src/modules/shortcut_guide/pch.h index 5b021e5eb3..63a1318c02 100644 --- a/src/modules/shortcut_guide/pch.h +++ b/src/modules/shortcut_guide/pch.h @@ -1,5 +1,7 @@ #pragma once #include +#include +#include #include #include #include diff --git a/src/modules/shortcut_guide/shortcut_guide.cpp b/src/modules/shortcut_guide/shortcut_guide.cpp index 0c70a7e5ae..708d4f43c5 100644 --- a/src/modules/shortcut_guide/shortcut_guide.cpp +++ b/src/modules/shortcut_guide/shortcut_guide.cpp @@ -11,6 +11,24 @@ extern "C" IMAGE_DOS_HEADER __ImageBase; OverlayWindow* instance = nullptr; +namespace +{ + LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) + { + LowlevelKeyboardEvent event; + if (nCode == HC_ACTION) + { + event.lParam = reinterpret_cast(lParam); + event.wParam = wParam; + if (instance->signal_event(&event) != 0) + { + return 1; + } + } + return CallNextHookEx(NULL, nCode, wParam, lParam); + } +} + OverlayWindow::OverlayWindow() { app_name = GET_RESOURCE_STRING(IDS_SHORTCUT_GUIDE); @@ -24,8 +42,7 @@ const wchar_t* OverlayWindow::get_name() const wchar_t** OverlayWindow::get_events() { - static const wchar_t* events[2] = { ll_keyboard, 0 }; - return events; + return nullptr; } bool OverlayWindow::get_config(wchar_t* buffer, int* buffer_size) @@ -117,6 +134,11 @@ void OverlayWindow::enable() winkey_popup->set_theme(theme.value); target_state = std::make_unique(pressTime.value); winkey_popup->initialize(); + hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL); + if (!hook_handle) + { + MessageBoxW(NULL, L"Cannot install keyboard listener.", L"PowerToys - Shortcut Guide", MB_OK | MB_ICONERROR); + } } _enabled = true; } @@ -134,6 +156,14 @@ void OverlayWindow::disable(bool trace_event) target_state->exit(); target_state.reset(); winkey_popup.reset(); + if (hook_handle) + { + bool success = UnhookWindowsHookEx(hook_handle); + if (success) + { + hook_handle = nullptr; + } + } } } @@ -149,22 +179,31 @@ bool OverlayWindow::is_enabled() intptr_t OverlayWindow::signal_event(const wchar_t* name, intptr_t data) { - if (_enabled && wcscmp(name, ll_keyboard) == 0) - { - auto& event = *(reinterpret_cast(data)); - if (event.wParam == WM_KEYDOWN || - event.wParam == WM_SYSKEYDOWN || - event.wParam == WM_KEYUP || - event.wParam == WM_SYSKEYUP) - { - bool supress = target_state->signal_event(event.lParam->vkCode, - event.wParam == WM_KEYDOWN || event.wParam == WM_SYSKEYDOWN); - return supress ? 1 : 0; - } - } return 0; } +intptr_t OverlayWindow::signal_event(LowlevelKeyboardEvent* event) +{ + if (!_enabled) + { + return 0; + } + + if (event->wParam == WM_KEYDOWN || + event->wParam == WM_SYSKEYDOWN || + event->wParam == WM_KEYUP || + event->wParam == WM_SYSKEYUP) + { + bool suppress = target_state->signal_event(event->lParam->vkCode, + event->wParam == WM_KEYDOWN || event->wParam == WM_SYSKEYDOWN); + return suppress ? 1 : 0; + } + else + { + return 0; + } +} + void OverlayWindow::on_held() { auto filter = get_shortcutguide_filtered_window(); diff --git a/src/modules/shortcut_guide/shortcut_guide.h b/src/modules/shortcut_guide/shortcut_guide.h index 61d0691e5b..c9f69679dc 100644 --- a/src/modules/shortcut_guide/shortcut_guide.h +++ b/src/modules/shortcut_guide/shortcut_guide.h @@ -22,6 +22,8 @@ public: virtual void enable() override; virtual void disable() override; virtual bool is_enabled() override; + + // PowerToys interface method, not used virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override; virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override {} @@ -32,6 +34,9 @@ public: void quick_hide(); void was_hidden(); + // Method called from LowLevelKeyboardProc + intptr_t signal_event(LowlevelKeyboardEvent* event); + virtual void destroy() override; private: @@ -39,6 +44,7 @@ private: std::unique_ptr target_state; std::unique_ptr winkey_popup; bool _enabled = false; + HHOOK hook_handle; void init_settings(); void disable(bool trace_event); diff --git a/src/modules/shortcut_guide/shortcut_guide.vcxproj b/src/modules/shortcut_guide/shortcut_guide.vcxproj index 76ce5825e5..8d2be26238 100644 --- a/src/modules/shortcut_guide/shortcut_guide.vcxproj +++ b/src/modules/shortcut_guide/shortcut_guide.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {A46629C4-1A6C-40FA-A8B6-10E5102BB0BA} Win32Proj overlaywindow - 10.0 + 10.0.17134.0 @@ -62,7 +63,6 @@ true true NDEBUG;OVERLAYWINDOW_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h MultiThreaded ..\..\common\inc;..\..\common\Telemetry;..\..\;..\;..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) @@ -83,7 +83,6 @@ Disabled true _DEBUG;OVERLAYWINDOW_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h MultiThreadedDebug ..\..\common\inc;..\..\common\Telemetry;..\..\;..\;..\..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories) @@ -124,7 +123,18 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/modules/shortcut_guide/shortcut_guide.vcxproj.filters b/src/modules/shortcut_guide/shortcut_guide.vcxproj.filters index 9d9a7c5088..9222c2fe27 100644 --- a/src/modules/shortcut_guide/shortcut_guide.vcxproj.filters +++ b/src/modules/shortcut_guide/shortcut_guide.vcxproj.filters @@ -49,4 +49,7 @@ + + + \ No newline at end of file diff --git a/src/runner/auto_start_helper.cpp b/src/runner/auto_start_helper.cpp index b979016ce3..e437cb484f 100644 --- a/src/runner/auto_start_helper.cpp +++ b/src/runner/auto_start_helper.cpp @@ -1,8 +1,6 @@ #include "pch.h" #include "auto_start_helper.h" -#include "general_settings.h" - #include #include @@ -10,8 +8,6 @@ #pragma comment(lib, "taskschd.lib") #pragma comment(lib, "comsupp.lib") -#include - // Helper macros from wix. // TODO: use "s" and "..." parameters to report errors from these functions. #define ExitOnFailure(x, s, ...) \ diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 2543f667ce..78fa23f2c8 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -4,7 +4,6 @@ #include #include "tray_icon.h" #include "powertoy_module.h" -#include "lowlevel_keyboard_event.h" #include "trace.h" #include "general_settings.h" #include "restart_elevated.h" diff --git a/src/runner/packages.config b/src/runner/packages.config index 4f733475e9..0e9399589b 100644 --- a/src/runner/packages.config +++ b/src/runner/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/src/runner/pch.h b/src/runner/pch.h index fa35d00897..a44644079a 100644 --- a/src/runner/pch.h +++ b/src/runner/pch.h @@ -1,5 +1,7 @@ #pragma once #include +#include +#include #include #include #include diff --git a/src/runner/powertoy_module.cpp b/src/runner/powertoy_module.cpp index 0e7866adf9..f141bcaa14 100644 --- a/src/runner/powertoy_module.cpp +++ b/src/runner/powertoy_module.cpp @@ -1,7 +1,5 @@ #include "pch.h" #include "powertoy_module.h" -#include "lowlevel_keyboard_event.h" -#include std::map& modules() { diff --git a/src/runner/powertoys_events.h b/src/runner/powertoys_events.h index 4135bfd477..2d5342fa62 100644 --- a/src/runner/powertoys_events.h +++ b/src/runner/powertoys_events.h @@ -3,6 +3,7 @@ #include #include #include +#include class PowertoysEvents { diff --git a/src/runner/runner.vcxproj b/src/runner/runner.vcxproj index 785a107f67..25734015a1 100644 --- a/src/runner/runner.vcxproj +++ b/src/runner/runner.vcxproj @@ -1,5 +1,6 @@  + Debug @@ -14,8 +15,8 @@ 15.0 {9412D5C6-2CF2-4FC2-A601-B55508EA9B27} powertoys - 10.0.18362.0 runner + 10.0.17134.0 @@ -57,7 +58,6 @@ Level3 Disabled true - true stdcpplatest MultiThreadedDebug Use @@ -82,7 +82,6 @@ true true true - true stdcpplatest MultiThreaded Use @@ -249,11 +248,14 @@ + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + \ No newline at end of file diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp index 7c2432c404..a3ad3dce47 100644 --- a/src/runner/settings_window.cpp +++ b/src/runner/settings_window.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include "powertoy_module.h" diff --git a/src/runner/update_utils.cpp b/src/runner/update_utils.cpp index 478f5e929c..8ab13a19b8 100644 --- a/src/runner/update_utils.cpp +++ b/src/runner/update_utils.cpp @@ -8,9 +8,6 @@ #include #include -#include -#include - bool start_msi_uninstallation_sequence() { const auto package_path = updating::get_msi_package_path(); diff --git a/src/settings/StreamUriResolverFromFile.h b/src/settings/StreamUriResolverFromFile.h index 03c7ff728e..43426c68bb 100644 --- a/src/settings/StreamUriResolverFromFile.h +++ b/src/settings/StreamUriResolverFromFile.h @@ -4,5 +4,6 @@ struct StreamUriResolverFromFile : winrt::implements { WCHAR base_path[MAX_PATH]; + winrt::Windows::Foundation::IAsyncOperation UriToStreamAsync(const winrt::Windows::Foundation::Uri& uri) const; }; diff --git a/src/settings/main.cpp b/src/settings/main.cpp index e15737924b..4f304449e4 100644 --- a/src/settings/main.cpp +++ b/src/settings/main.cpp @@ -40,8 +40,6 @@ HWND g_main_wnd = nullptr; WebViewControl g_webview = nullptr; WebViewControlProcess g_webview_process = nullptr; -StreamUriResolverFromFile local_uri_resolver; - // Windows message for receiving copied data to send to the webview. UINT wm_data_for_webview = 0; @@ -71,12 +69,13 @@ void NavigateToLocalhostReactServer() void NavigateToUri(_In_ LPCWSTR uri_as_string) { + auto uri_resolver = winrt::make_self(); // initialize the base_path for the html content relative to the executable. - WINRT_VERIFY(GetModuleFileName(nullptr, local_uri_resolver.base_path, MAX_PATH)); - WINRT_VERIFY(PathRemoveFileSpec(local_uri_resolver.base_path)); - wcscat_s(local_uri_resolver.base_path, URI_CONTENT_ID); + WINRT_VERIFY(GetModuleFileName(nullptr, uri_resolver->base_path, MAX_PATH)); + WINRT_VERIFY(PathRemoveFileSpec(uri_resolver->base_path)); + wcscat_s(uri_resolver->base_path, URI_CONTENT_ID); Uri url = g_webview.BuildLocalStreamUri(hstring(URI_CONTENT_ID), hstring(uri_as_string)); - g_webview.NavigateToLocalStreamUri(url, local_uri_resolver); + g_webview.NavigateToLocalStreamUri(url, *uri_resolver); } Rect client_rect_to_bounds_rect(_In_ HWND hwnd) diff --git a/src/settings/packages.config b/src/settings/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/src/settings/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/settings/pch.h b/src/settings/pch.h index 735fe1c956..8fbd24f9db 100644 --- a/src/settings/pch.h +++ b/src/settings/pch.h @@ -4,15 +4,18 @@ #pragma push_macro("GetCurrentTime") #undef GetCurrentTime // include winrt headers with fix for "warning C4002: Too many arguments for function-like macro invocation GetCurrentTime" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #pragma pop_macro("GetCurrentTime") #include #include diff --git a/src/settings/settings.vcxproj b/src/settings/settings.vcxproj index b9c55a4d94..f654c9b6c6 100644 --- a/src/settings/settings.vcxproj +++ b/src/settings/settings.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -14,7 +15,7 @@ 15.0 {07C389E3-6BC8-41CF-923E-307B1265FA2D} PowerToysSettingsEditor - 10.0 + 10.0.17134.0 settings @@ -56,7 +57,6 @@ Level3 Disabled true - true stdcpplatest Use pch.h @@ -85,7 +85,6 @@ true true true - true stdcpplatest Use pch.h @@ -137,7 +136,18 @@ {74485049-c722-400f-abe5-86ac52d929b3} + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/settings/settings.vcxproj.filters b/src/settings/settings.vcxproj.filters index 40f02e0184..ef76513ecd 100644 --- a/src/settings/settings.vcxproj.filters +++ b/src/settings/settings.vcxproj.filters @@ -52,4 +52,7 @@ Resource Files + + + \ No newline at end of file diff --git a/src/tests/win-app-driver/FancyZonesTests/FancyZonesSettingsTests.cs b/src/tests/win-app-driver/FancyZonesTests/FancyZonesSettingsTests.cs index d655b7960b..d1ece9216e 100644 --- a/src/tests/win-app-driver/FancyZonesTests/FancyZonesSettingsTests.cs +++ b/src/tests/win-app-driver/FancyZonesTests/FancyZonesSettingsTests.cs @@ -305,13 +305,14 @@ namespace PowerToysTests JObject savedProps = GetProperties(); Assert.AreNotEqual(toggleValues[0], GetPropertyValue(savedProps, "fancyzones_shiftDrag")); Assert.AreNotEqual(toggleValues[1], GetPropertyValue(savedProps, "fancyzones_overrideSnapHotkeys")); - Assert.AreNotEqual(toggleValues[2], GetPropertyValue(savedProps, "fancyzones_displayChange_moveWindows")); - Assert.AreNotEqual(toggleValues[3], GetPropertyValue(savedProps, "fancyzones_zoneSetChange_moveWindows")); - Assert.AreNotEqual(toggleValues[4], GetPropertyValue(savedProps, "fancyzones_virtualDesktopChange_moveWindows")); - Assert.AreNotEqual(toggleValues[5], GetPropertyValue(savedProps, "fancyzones_appLastZone_moveWindows")); - Assert.AreNotEqual(toggleValues[6], GetPropertyValue(savedProps, "use_cursorpos_editor_startupscreen")); - Assert.AreNotEqual(toggleValues[7], GetPropertyValue(savedProps, "fancyzones_show_on_all_monitors")); - Assert.AreNotEqual(toggleValues[8], GetPropertyValue(savedProps, "fancyzones_makeDraggedWindowTransparent")); + Assert.AreNotEqual(toggleValues[2], GetPropertyValue(savedProps, "fancyzones_moveWindowAcrossMonitors")); + Assert.AreNotEqual(toggleValues[3], GetPropertyValue(savedProps, "fancyzones_displayChange_moveWindows")); + Assert.AreNotEqual(toggleValues[4], GetPropertyValue(savedProps, "fancyzones_zoneSetChange_moveWindows")); + Assert.AreNotEqual(toggleValues[5], GetPropertyValue(savedProps, "fancyzones_virtualDesktopChange_moveWindows")); + Assert.AreNotEqual(toggleValues[6], GetPropertyValue(savedProps, "fancyzones_appLastZone_moveWindows")); + Assert.AreNotEqual(toggleValues[7], GetPropertyValue(savedProps, "use_cursorpos_editor_startupscreen")); + Assert.AreNotEqual(toggleValues[8], GetPropertyValue(savedProps, "fancyzones_show_on_all_monitors")); + Assert.AreNotEqual(toggleValues[9], GetPropertyValue(savedProps, "fancyzones_makeDraggedWindowTransparent")); } /* @@ -343,13 +344,14 @@ namespace PowerToysTests JObject savedProps = GetProperties(); Assert.AreEqual(toggleValues[0], GetPropertyValue(savedProps, "fancyzones_shiftDrag")); Assert.AreEqual(toggleValues[1], GetPropertyValue(savedProps, "fancyzones_overrideSnapHotkeys")); - Assert.AreEqual(toggleValues[2], GetPropertyValue(savedProps, "fancyzones_displayChange_moveWindows")); - Assert.AreEqual(toggleValues[3], GetPropertyValue(savedProps, "fancyzones_zoneSetChange_moveWindows")); - Assert.AreEqual(toggleValues[4], GetPropertyValue(savedProps, "fancyzones_virtualDesktopChange_moveWindows")); - Assert.AreEqual(toggleValues[5], GetPropertyValue(savedProps, "fancyzones_appLastZone_moveWindows")); - Assert.AreEqual(toggleValues[6], GetPropertyValue(savedProps, "use_cursorpos_editor_startupscreen")); - Assert.AreEqual(toggleValues[7], GetPropertyValue(savedProps, "fancyzones_show_on_all_monitors")); - Assert.AreEqual(toggleValues[8], GetPropertyValue(savedProps, "fancyzones_makeDraggedWindowTransparent")); + Assert.AreEqual(toggleValues[2], GetPropertyValue(savedProps, "fancyzones_moveWindowAcrossMonitors")); + Assert.AreEqual(toggleValues[3], GetPropertyValue(savedProps, "fancyzones_displayChange_moveWindows")); + Assert.AreEqual(toggleValues[4], GetPropertyValue(savedProps, "fancyzones_zoneSetChange_moveWindows")); + Assert.AreEqual(toggleValues[5], GetPropertyValue(savedProps, "fancyzones_virtualDesktopChange_moveWindows")); + Assert.AreEqual(toggleValues[6], GetPropertyValue(savedProps, "fancyzones_appLastZone_moveWindows")); + Assert.AreEqual(toggleValues[7], GetPropertyValue(savedProps, "use_cursorpos_editor_startupscreen")); + Assert.AreEqual(toggleValues[8], GetPropertyValue(savedProps, "fancyzones_show_on_all_monitors")); + Assert.AreEqual(toggleValues[9], GetPropertyValue(savedProps, "fancyzones_makeDraggedWindowTransparent")); } [TestMethod] diff --git a/src/tests/win-app-driver/PowerToysSession.cs b/src/tests/win-app-driver/PowerToysSession.cs index 150938367f..7adfa5c4f2 100644 --- a/src/tests/win-app-driver/PowerToysSession.cs +++ b/src/tests/win-app-driver/PowerToysSession.cs @@ -26,7 +26,7 @@ namespace PowerToysTests protected static string _initialSettings = ""; protected static string _initialZoneSettings = ""; - protected const string _defaultSettings = "{\"version\":\"1.0\",\"name\":\"FancyZones\",\"properties\":{\"fancyzones_shiftDrag\":{\"value\":true},\"fancyzones_overrideSnapHotkeys\":{\"value\":false},\"fancyzones_zoneSetChange_flashZones\":{\"value\":false},\"fancyzones_displayChange_moveWindows\":{\"value\":false},\"fancyzones_zoneSetChange_moveWindows\":{\"value\":false},\"fancyzones_virtualDesktopChange_moveWindows\":{\"value\":false},\"fancyzones_appLastZone_moveWindows\":{\"value\":false},\"use_cursorpos_editor_startupscreen\":{\"value\":true},\"fancyzones_zoneHighlightColor\":{\"value\":\"#0078D7\"},\"fancyzones_highlight_opacity\":{\"value\":90},\"fancyzones_editor_hotkey\":{\"value\":{\"win\":true,\"ctrl\":false,\"alt\":false,\"shift\":false,\"code\":192,\"key\":\"`\"}},\"fancyzones_excluded_apps\":{\"value\":\"\"}}}"; + protected const string _defaultSettings = "{\"version\":\"1.0\",\"name\":\"FancyZones\",\"properties\":{\"fancyzones_shiftDrag\":{\"value\":true},\"fancyzones_overrideSnapHotkeys\":{\"value\":false},\"fancyzones_moveWindowAcrossMonitors\":{\"value\":false},\"fancyzones_zoneSetChange_flashZones\":{\"value\":false},\"fancyzones_displayChange_moveWindows\":{\"value\":false},\"fancyzones_zoneSetChange_moveWindows\":{\"value\":false},\"fancyzones_virtualDesktopChange_moveWindows\":{\"value\":false},\"fancyzones_appLastZone_moveWindows\":{\"value\":false},\"use_cursorpos_editor_startupscreen\":{\"value\":true},\"fancyzones_zoneHighlightColor\":{\"value\":\"#0078D7\"},\"fancyzones_highlight_opacity\":{\"value\":90},\"fancyzones_editor_hotkey\":{\"value\":{\"win\":true,\"ctrl\":false,\"alt\":false,\"shift\":false,\"code\":192,\"key\":\"`\"}},\"fancyzones_excluded_apps\":{\"value\":\"\"}}}"; protected const string _defaultZoneSettings = "{\"app-zone-history\":[],\"devices\":[],\"custom-zone-sets\":[]}"; diff --git a/tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj b/tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj index cdb6f2b7fe..9fde29ba69 100644 --- a/tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj +++ b/tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -15,7 +16,7 @@ {64A80062-4D8B-4229-8A38-DFA1D7497749} Win32Proj templatenamespace - 10.0 + 10.0.17134.0 ModuleTemplateCompileTest @@ -61,7 +62,6 @@ Disabled true _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h MultiThreadedDebug stdcpplatest @@ -81,7 +81,6 @@ true true NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true pch.h MultiThreaded stdcpplatest @@ -122,7 +121,18 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj.filters b/tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj.filters index 4b1a91f13c..d06043800f 100644 --- a/tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj.filters +++ b/tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj.filters @@ -13,4 +13,7 @@ + + + \ No newline at end of file diff --git a/tools/project_template/ModuleTemplate/packages.config b/tools/project_template/ModuleTemplate/packages.config new file mode 100644 index 0000000000..1447e714af --- /dev/null +++ b/tools/project_template/ModuleTemplate/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tools/project_template/ModuleTemplate/pch.h b/tools/project_template/ModuleTemplate/pch.h index 769a37b377..c981591a05 100644 --- a/tools/project_template/ModuleTemplate/pch.h +++ b/tools/project_template/ModuleTemplate/pch.h @@ -1,5 +1,7 @@ #pragma once #define WIN32_LEAN_AND_MEAN #include +#include +#include #include #include \ No newline at end of file