Compare commits

...

11 commits

Author SHA1 Message Date
Clint Rutkas 72ea4ff8b3
Hero tweak (#14645)
* Update README.md

* Update README.md

* tweaking path
2021-11-26 12:26:32 -08:00
Deondre Davis 991124c9e4
Preview pane toggle instructions (#14595)
* Added informative text about toggling preview pane in settings

* Update Resources.resw

* Changed infobar to textblock

* Update src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw

Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com>

Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com>
2021-11-26 15:00:28 +01:00
Jaime Bernardo 47b5386c0c
[ci][PTRun]Fix signing for new plugins folders (#14646) 2021-11-25 18:40:02 +00:00
FLOAT4 5381486c25
[FancyZones] Rename ZoneWindowDrawing -> ZonesDrawing (#14464)
* [FancyZones] Rename ZoneWindowDrawing -> ZonesOverlay

* [FancyZones] Rename ZoneWindowDrawing -> ZonesOverlay in tools and docs

Co-authored-by: float4 <float4-unspecified-mail>
2021-11-25 16:39:03 +01:00
Jaime Bernardo 375ce4c798
[ci][binskim]skip cppwinrt.exe binary checks (#14628) 2021-11-24 12:05:54 -08:00
Niels Laute d2c6148662
[PowerRename] Resolve UI focus issue (#14605)
* UI tweaks

* Fixed 0 margins

* Fixed height for button

* Update MainWindow.xaml
2021-11-24 18:45:31 +00:00
Jaime Bernardo 84101ab821
[ci][powerpreview]Add include to fix build error (#14624) 2021-11-24 11:09:06 +00:00
Seraphima Zykova bd0db76e31
[FancyZones] Crash on launch: fix exception handler (#14609)
* fix stacktrace logging

* init logger before exception handler

* wchar check
2021-11-23 18:41:10 +00:00
Clint Rutkas 8743c2329e
Show color as a float and as a decimal value (#14548)
* #14020 and #12630 - Show color as a float and as a decimal value

* getting stuff up-to-par

* changing RGB Float to VEC4

* Getting Decimal to display correct.

* tweaking VEC4 output.  What would be better is if these actually pulled from a real output ...

* Shifting to force decimal

Co-authored-by: Clint Rutkas <crutkas@microsoft.com>
2021-11-23 09:08:01 -08:00
Jaime Bernardo 46244e8e84
[FindMyMouse]Add additional settings (#14590)
* [FindMyMouse]Add additional settings

* Add setting for Spotlight Initial Zoom

* PR feedback: lowercase settings names

* PR feedback: settings descriptions

* PR feedback: change opacity to percentage

* PR feedback: increase maximum zoom factor

* PR feedback: group spotlight settings

* PR feedback: Expanders start collapsed initially

* Remove extra settings file save in dllmain

* PR feedback: change initial zoom description

* PR feedback: Add warning for photo sensitive users

* PR feedback: remove warning and add description instead

* PR feedback: size->factor in initial zoom description

* Feedback PR: remove opacity description

* PR feedback: remove photo sensitivity warning
2021-11-23 16:52:17 +00:00
Stefan Markovic 8afac77841
[ColorPicker] Accept lower-case hex code in AdjustColor window HEX text block (#14602) 2021-11-23 16:40:12 +01:00
36 changed files with 762 additions and 677 deletions

View file

@ -138,24 +138,24 @@ build:
- 'modules\launcher\Microsoft.Launcher.dll'
- 'modules\launcher\Plugins\Calculator\Microsoft.PowerToys.Run.Plugin.Calculator.dll'
- 'modules\launcher\Plugins\Calculator\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Folder\Microsoft.Plugin.Folder.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Folder\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Indexer\Microsoft.Plugin.Indexer.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Indexer\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Program\Microsoft.Plugin.Program.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Program\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\Microsoft.PowerToys.Run.Plugin.Registry.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\WindowsSettings.json'
- 'modules\launcher\Plugins\Microsoft.Plugin.Shell\Microsoft.Plugin.Shell.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Shell\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Uri\Microsoft.Plugin.Uri.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Uri\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\Microsoft.Plugin.WindowWalker.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Community.UnitConverter\Community.PowerToys.Run.Plugin.UnitConverter.dll'
- 'modules\launcher\Plugins\Folder\Microsoft.Plugin.Folder.dll'
- 'modules\launcher\Plugins\Folder\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Indexer\Microsoft.Plugin.Indexer.dll'
- 'modules\launcher\Plugins\Indexer\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Program\Microsoft.Plugin.Program.dll'
- 'modules\launcher\Plugins\Program\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Registry\Microsoft.PowerToys.Run.Plugin.Registry.dll'
- 'modules\launcher\Plugins\Registry\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\WindowsSettings\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll'
- 'modules\launcher\Plugins\WindowsSettings\WindowsSettings.json'
- 'modules\launcher\Plugins\Shell\Microsoft.Plugin.Shell.dll'
- 'modules\launcher\Plugins\Shell\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Uri\Microsoft.Plugin.Uri.dll'
- 'modules\launcher\Plugins\Uri\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\WindowWalker\Microsoft.Plugin.WindowWalker.dll'
- 'modules\launcher\Plugins\WindowWalker\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\UnitConverter\Community.PowerToys.Run.Plugin.UnitConverter.dll'
- 'modules\launcher\Plugins\VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.dll'
- 'modules\launcher\Plugins\Service\Microsoft.PowerToys.Run.Plugin.Service.dll'
- 'modules\launcher\Plugins\System\Microsoft.PowerToys.Run.Plugin.System.dll'
@ -255,6 +255,7 @@ static_analysis_options:
exclude:
- 'WiX.*/**/*.dll'
- 'Wix.*/**/*.exe'
- 'Microsoft.Windows.CppWinRT.*/**/*.exe'
moderncop_options:
files_to_scan:
- from: 'src'

View file

@ -262,6 +262,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643-4663-475E-B329-03F0C9918D48}"
ProjectSection(SolutionItems) = preProject
src\common\utils\appMutex.h = src\common\utils\appMutex.h
src\common\utils\color.h = src\common\utils\color.h
src\common\utils\com_object_factory.h = src\common\utils\com_object_factory.h
src\common\utils\elevation.h = src\common\utils\elevation.h
src\common\utils\EventLocker.h = src\common\utils\EventLocker.h

View file

@ -1,6 +1,6 @@
# Microsoft PowerToys
<img src="./doc/images/overview/PT%20hero%20image.png"/>
![Hero image for Microsoft PowerToys](doc/images/overview/PT_hero_image.png)
[How to use PowerToys][usingPowerToys-docs-link] | [Downloads & Release notes][github-release-link] | [Contributing to PowerToys](#contributing) | [What's Happening](#whats-happening) | [Roadmap](#powertoys-roadmap)

View file

@ -15,7 +15,7 @@ TODO
#### [`ZoneSet.cpp`](/src/modules/fancyzones/lib/ZoneSet.cpp)
TODO
#### [`ZoneWindow.cpp`](/src/modules/fancyzones/lib/ZoneWindow.cpp)
#### [`WorkArea.cpp`](/src/modules/fancyzones/lib/WorkArea.cpp)
TODO
## FancyZones Editor

View file

Before

Width:  |  Height:  |  Size: 447 KiB

After

Width:  |  Height:  |  Size: 447 KiB

View file

@ -2,17 +2,17 @@
---
1. `Zone` - Class which is basically wrapper around rectangle structure, representing one zone inside applied zone layout. ZoneSet is holding array of these which represent zone layout.
2. `ZoneSet` - Class implementing actual zone layout applied. What this means is that ZoneSet is responsible for actual calculation of rectangle coordinates (whether is grid or canvas layout) and moving window through them. ZoneWindow holds ZoneSet structure which represents currently active zone set.
3. `ZoneWindow` - Class representing work area, which is defined by monitor and current virtual desktop. For an example, if You have two monitors connected and two virtual desktops, You have 4 work areas available, and each of them can have separate zone layout. ZoneWindow is describing single work area. As mentioned before it holds active ZoneSet.
2. `ZoneSet` - Class implementing actual zone layout applied. What this means is that ZoneSet is responsible for actual calculation of rectangle coordinates (whether is grid or canvas layout) and moving window through them. WorkArea holds ZoneSet structure which represents currently active zone set.
3. `WorkArea` - Class representing work area, which is defined by monitor and current virtual desktop. For an example, if You have two monitors connected and two virtual desktops, You have 4 work areas available, and each of them can have separate zone layout. WorkArea is describing single work area. As mentioned before it holds active ZoneSet.
4. `FancyZones` - Top level entity and entry point for all user actions (which goes through actual module interface). Some of the main responsibilities of FancyZones class:
1. Starting FancyZones Editor (C#) with appropriate command line arguments on user request.
2. Keeping track of ZoneWindow per monitor (currently active work area on each connected monitor).
2. Keeping track of WorkArea per monitor (currently active work area on each connected monitor).
3. Keeping track of active virtual desktops. This is performed in separate thread by polling VirtualDesktopIDs registry key and parsing its content.
4. Detecting every change in work environment, such as creating / destroying / switching between virtual desktops, closing FancyZones Editor, changing display settings and handling those changes.
### Proposal for modifications of handling described in 4.4:
Currently after each of the mentioned changes in work environment we are calling EnumDisplayMonitors windows API, and passing callback function to it. EnumDisplayMonitors works asynchronous and triggers that callback for each work area available (as mentioned in previous example, for two monitors and two virtual desktops, we have this callback triggered four times). As mentioned previously, we have ZoneWindow class as our representation of this work area. And what we do, every time this callback is triggered we destroy previous ZoneWindow object for that work area and create new one, even though that it is most likely that nothing has changed (e.g. just switching back and forth between virtual desktops). This constant creation and deletion of ZoneWindow has caused some problems in the past and it's not ideal for some other fixes we would like to make in the multi-monitor/multi-desktop scenario.
Currently after each of the mentioned changes in work environment we are calling EnumDisplayMonitors windows API, and passing callback function to it. EnumDisplayMonitors works asynchronous and triggers that callback for each work area available (as mentioned in previous example, for two monitors and two virtual desktops, we have this callback triggered four times). As mentioned previously, we have WorkArea class as our representation of this work area. And what we do, every time this callback is triggered we destroy previous WorkArea object for that work area and create new one, even though that it is most likely that nothing has changed (e.g. just switching back and forth between virtual desktops). This constant creation and deletion of WorkArea has caused some problems in the past and it's not ideal for some other fixes we would like to make in the multi-monitor/multi-desktop scenario.
As mentioned in 4.3 we already have tracker of virtual desktops implemented. Idea is to use this functionality and to extend it bit more, so we can track if work area (ZoneWindow) is new one, or already processed and skip creating new ZoneWindow objects and deleting old ones every time, even if nothing changed in it. We will keep map, where virtual desktop id is the key, and values are already processed monitors (virtual desktop exists across all monitors). Once we receive callback from EnumDisplayMonitors, indicating work area (defined by virtual desktop id and monitor) we can check if its new or not, and act accordingly (create new ZoneWindow for it or not). Deleting virtual desktop (which is also registered in 4.3), will trigger updates in this map, and also updates in our JSON storage.
As mentioned in 4.3 we already have tracker of virtual desktops implemented. Idea is to use this functionality and to extend it bit more, so we can track if work area (WorkArea) is new one, or already processed and skip creating new WorkArea objects and deleting old ones every time, even if nothing changed in it. We will keep map, where virtual desktop id is the key, and values are already processed monitors (virtual desktop exists across all monitors). Once we receive callback from EnumDisplayMonitors, indicating work area (defined by virtual desktop id and monitor) we can check if its new or not, and act accordingly (create new WorkArea for it or not). Deleting virtual desktop (which is also registered in 4.3), will trigger updates in this map, and also updates in our JSON storage.

View file

@ -9,10 +9,7 @@
#include "winapi_error.h"
#include "../logger/logger.h"
static IMAGEHLP_SYMBOL64* pSymbol = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH * sizeof(TCHAR));
static IMAGEHLP_LINE64 line;
static BOOLEAN processingException = FALSE;
static CHAR modulePath[MAX_PATH];
static inline const char* exceptionDescription(const DWORD& code)
{
@ -64,15 +61,15 @@ static inline const char* exceptionDescription(const DWORD& code)
}
/* Returns the index of the last backslash in the file path */
inline int GetFilenameStart(CHAR* path)
inline int GetFilenameStart(wchar_t* path)
{
int pos = 0;
int found = 0;
if (path != NULL)
{
while (path[pos] != '\0' && pos < MAX_PATH)
while (path[pos] != L'\0' && pos < MAX_PATH)
{
if (path[pos] == '\\')
if (path[pos] == L'\\')
{
found = pos + 1;
}
@ -83,22 +80,73 @@ inline int GetFilenameStart(CHAR* path)
return found;
}
inline void LogStackTrace()
inline std::wstring GetModuleName(HANDLE process, const STACKFRAME64& stack)
{
BOOL result;
HANDLE thread;
HANDLE process;
CONTEXT context;
STACKFRAME64 stack;
ULONG frame;
DWORD64 dw64Displacement;
DWORD dwDisplacement;
static wchar_t modulePath[MAX_PATH]{};
const size_t size = sizeof(modulePath);
memset(&modulePath[0], '\0', size);
DWORD64 moduleBase = SymGetModuleBase64(process, stack.AddrPC.Offset);
if (!moduleBase)
{
Logger::error(L"Failed to get a module. {}", get_last_error_or_default(GetLastError()));
return std::wstring();
}
if (!GetModuleFileNameW((HINSTANCE)moduleBase, modulePath, MAX_PATH))
{
Logger::error(L"Failed to get a module path. {}", get_last_error_or_default(GetLastError()));
return std::wstring();
}
const int start = GetFilenameStart(modulePath);
return std::wstring(modulePath, start);
}
inline std::wstring GetName(HANDLE process, const STACKFRAME64& stack)
{
static IMAGEHLP_SYMBOL64* pSymbol = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH * sizeof(TCHAR));
if (!pSymbol)
{
return std::wstring();
}
memset(&stack, 0, sizeof(STACKFRAME64));
memset(pSymbol, '\0', sizeof(*pSymbol) + MAX_PATH);
memset(&modulePath[0], '\0', sizeof(modulePath));
pSymbol->MaxNameLength = MAX_PATH;
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
DWORD64 dw64Displacement = 0;
if (!SymGetSymFromAddr64(process, stack.AddrPC.Offset, &dw64Displacement, pSymbol))
{
Logger::error(L"Failed to get a symbol. {}", get_last_error_or_default(GetLastError()));
return std::wstring();
}
std::string str = pSymbol->Name;
return std::wstring(str.begin(), str.end());
}
inline std::wstring GetLine(HANDLE process, const STACKFRAME64& stack)
{
static IMAGEHLP_LINE64 line{};
memset(&line, '\0', sizeof(IMAGEHLP_LINE64));
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
line.LineNumber = 0;
DWORD dwDisplacement = 0;
if (!SymGetLineFromAddr64(process, stack.AddrPC.Offset, &dwDisplacement, &line))
{
return std::wstring();
}
std::string fileName(line.FileName);
return L"(" + std::wstring(fileName.begin(), fileName.end()) + L":" + std::to_wstring(line.LineNumber) + L")";
}
inline void LogStackTrace()
{
CONTEXT context;
try
{
RtlCaptureContext(&context);
@ -109,9 +157,11 @@ inline void LogStackTrace()
return;
}
process = GetCurrentProcess();
thread = GetCurrentThread();
dw64Displacement = 0;
STACKFRAME64 stack;
memset(&stack, 0, sizeof(STACKFRAME64));
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
stack.AddrPC.Offset = context.Rip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = context.Rsp;
@ -119,8 +169,9 @@ inline void LogStackTrace()
stack.AddrFrame.Offset = context.Rbp;
stack.AddrFrame.Mode = AddrModeFlat;
std::stringstream ss;
for (frame = 0;; frame++)
BOOL result = false;
std::wstringstream ss;
for (;;)
{
result = StackWalk64(
IMAGE_FILE_MACHINE_AMD64,
@ -138,34 +189,10 @@ inline void LogStackTrace()
break;
}
pSymbol->MaxNameLength = MAX_PATH;
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
if (!SymGetSymFromAddr64(process, stack.AddrPC.Offset, &dw64Displacement, pSymbol))
{
Logger::error(L"Failed to get a symbol. {}", get_last_error_or_default(GetLastError()));
}
line.LineNumber = 0;
SymGetLineFromAddr64(process, stack.AddrPC.Offset, &dwDisplacement, &line);
DWORD64 moduleBase = SymGetModuleBase64(process, stack.AddrPC.Offset);
if (moduleBase)
{
if (!GetModuleFileNameA((HINSTANCE)moduleBase, modulePath, MAX_PATH))
{
Logger::error(L"Failed to get a module path. {}", get_last_error_or_default(GetLastError()));
}
}
else
{
Logger::error(L"Failed to get a module. {}", get_last_error_or_default(GetLastError()));
}
ss << std::string(modulePath).substr(GetFilenameStart(modulePath)) << "!" << pSymbol->Name << "(" << line.FileName << ":" << line.LineNumber << std::endl;
ss << GetModuleName(process, stack) << "!" << GetName(process, stack) << GetLine(process, stack) << std::endl;
}
Logger::error("STACK TRACE\r\n{}", ss.str());
Logger::error(L"STACK TRACE\r\n{}", ss.str());
Logger::flush();
}
@ -218,7 +245,6 @@ inline void InitSymbols()
{
// Preload symbols so they will be available in case of out-of-memory exception
SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
HANDLE process = GetCurrentProcess();
if (!SymInitialize(process, NULL, TRUE))
{

21
src/common/utils/color.h Normal file
View file

@ -0,0 +1,21 @@
#pragma once
// helper function to get the RGB from a #FFFFFF string.
inline bool checkValidRGB(std::wstring_view hex, uint8_t* R, uint8_t* G, uint8_t* B)
{
if (hex.length() != 7)
return false;
hex = hex.substr(1, 6); // remove #
for (auto& c : hex)
{
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')))
{
return false;
}
}
if (swscanf_s(hex.data(), L"%2hhx%2hhx%2hhx", R, G, B) != 3)
{
return false;
}
return true;
}

View file

@ -8,6 +8,7 @@
#include <vector>
#include <optional>
#include <cassert>
#include <sstream>
#include "../logger/logger.h"
#include "../utils/winapi_error.h"

View file

@ -19,8 +19,6 @@ namespace ABI
}
#endif
bool m_doNotActivateOnGameMode = true;
#pragma region Super_Sonar_Base_Code
template<typename D>
@ -58,11 +56,13 @@ protected:
// At actual check, time a fifth of the current double click setting might be used instead to take into account users who might have low values.
static const int MIN_DOUBLE_CLICK_TIME = 100;
static constexpr int SonarRadius = 100;
static constexpr int SonarZoomFactor = 9;
static constexpr DWORD FadeDuration = 500;
static constexpr int FinalAlphaNumerator = 1;
static constexpr int FinalAlphaDenominator = 2;
bool m_destroyed = false;
bool m_doNotActivateOnGameMode = true;
int m_sonarRadius = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_RADIUS;
int m_sonarZoomFactor = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM;
DWORD m_fadeDuration = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS;
int m_finalAlphaNumerator = FIND_MY_MOUSE_DEFAULT_OVERLAY_OPACITY;
static constexpr int FinalAlphaDenominator = 100;
winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
private:
@ -150,6 +150,7 @@ void SuperSonar<D>::Terminate()
{
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
m_destroyed = true;
DestroyWindow(m_hwndOwner);
});
if (!enqueueSucceeded)
@ -457,7 +458,7 @@ void SuperSonar<D>::UpdateMouseSnooping()
struct CompositionSpotlight : SuperSonar<CompositionSpotlight>
{
static constexpr UINT WM_OPACITY_ANIMATION_COMPLETED = WM_APP;
static constexpr float SonarRadiusFloat = static_cast<float>(SonarRadius);
float m_sonarRadiusFloat = static_cast<float>(m_sonarRadius);
DWORD GetExtendedStyle()
{
@ -489,7 +490,7 @@ struct CompositionSpotlight : SuperSonar<CompositionSpotlight>
m_batch.Completed([hwnd = m_hwnd](auto&&, auto&&) {
PostMessage(hwnd, WM_OPACITY_ANIMATION_COMPLETED, 0, 0);
});
m_root.Opacity(visible ? static_cast<float>(FinalAlphaNumerator) / FinalAlphaDenominator : 0.0f);
m_root.Opacity(visible ? static_cast<float>(m_finalAlphaNumerator) / FinalAlphaDenominator : 0.0f);
if (visible)
{
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
@ -531,38 +532,38 @@ private:
layer.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
m_root.Children().InsertAtTop(layer);
auto backdrop = m_compositor.CreateSpriteVisual();
backdrop.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
backdrop.Brush(m_compositor.CreateColorBrush({ 255, 0, 0, 0 }));
layer.Children().InsertAtTop(backdrop);
m_backdrop = m_compositor.CreateSpriteVisual();
m_backdrop.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
m_backdrop.Brush(m_compositor.CreateColorBrush(m_backgroundColor));
layer.Children().InsertAtTop(m_backdrop);
m_circleGeometry = m_compositor.CreateEllipseGeometry(); // radius set via expression animation
auto circleShape = m_compositor.CreateSpriteShape(m_circleGeometry);
circleShape.FillBrush(m_compositor.CreateColorBrush({ 255, 255, 255, 255 }));
circleShape.Offset({ SonarRadiusFloat * SonarZoomFactor, SonarRadiusFloat * SonarZoomFactor });
m_circleShape = m_compositor.CreateSpriteShape(m_circleGeometry);
m_circleShape.FillBrush(m_compositor.CreateColorBrush(m_spotlightColor));
m_circleShape.Offset({ m_sonarRadiusFloat * m_sonarZoomFactor, m_sonarRadiusFloat * m_sonarZoomFactor });
m_spotlight = m_compositor.CreateShapeVisual();
m_spotlight.Size({ SonarRadiusFloat * 2 * SonarZoomFactor, SonarRadiusFloat * 2 * SonarZoomFactor });
m_spotlight.Size({ m_sonarRadiusFloat * 2 * m_sonarZoomFactor, m_sonarRadiusFloat * 2 * m_sonarZoomFactor });
m_spotlight.AnchorPoint({ 0.5f, 0.5f });
m_spotlight.Shapes().Append(circleShape);
m_spotlight.Shapes().Append(m_circleShape);
layer.Children().InsertAtTop(m_spotlight);
// Implicitly animate the alpha.
auto animation = m_compositor.CreateScalarKeyFrameAnimation();
animation.Target(L"Opacity");
animation.InsertExpressionKeyFrame(1.0f, L"this.FinalValue");
animation.Duration(std::chrono::milliseconds{ FadeDuration });
m_animation = m_compositor.CreateScalarKeyFrameAnimation();
m_animation.Target(L"Opacity");
m_animation.InsertExpressionKeyFrame(1.0f, L"this.FinalValue");
m_animation.Duration(std::chrono::milliseconds{ m_fadeDuration });
auto collection = m_compositor.CreateImplicitAnimationCollection();
collection.Insert(L"Opacity", animation);
collection.Insert(L"Opacity", m_animation);
m_root.ImplicitAnimations(collection);
// Radius of spotlight shrinks as opacity increases.
// At opacity zero, it is SonarRadius * SonarZoomFactor.
// At maximum opacity, it is SonarRadius.
// At opacity zero, it is m_sonarRadius * SonarZoomFactor.
// At maximum opacity, it is m_sonarRadius.
auto radiusExpression = m_compositor.CreateExpressionAnimation();
radiusExpression.SetReferenceParameter(L"Root", m_root);
wchar_t expressionText[256];
winrt::check_hresult(StringCchPrintfW(expressionText, ARRAYSIZE(expressionText), L"Lerp(Vector2(%d, %d), Vector2(%d, %d), Root.Opacity * %d / %d)", SonarRadius * SonarZoomFactor, SonarRadius * SonarZoomFactor, SonarRadius, SonarRadius, FinalAlphaDenominator, FinalAlphaNumerator));
winrt::check_hresult(StringCchPrintfW(expressionText, ARRAYSIZE(expressionText), L"Lerp(Vector2(%d, %d), Vector2(%d, %d), Root.Opacity * %d / %d)", m_sonarRadius * m_sonarZoomFactor, m_sonarRadius * m_sonarZoomFactor, m_sonarRadius, m_sonarRadius, FinalAlphaDenominator, m_finalAlphaNumerator));
radiusExpression.Expression(expressionText);
m_circleGeometry.StartAnimation(L"Radius", radiusExpression);
@ -581,6 +582,62 @@ private:
}
}
public:
void ApplySettings(const FindMyMouseSettings& settings, bool applyToRuntimeObjects) {
if (!applyToRuntimeObjects)
{
// Runtime objects not created yet. Just update fields.
m_sonarRadius = settings.spotlightRadius;
m_sonarRadiusFloat = static_cast<float>(m_sonarRadius);
m_backgroundColor = settings.backgroundColor;
m_spotlightColor = settings.spotlightColor;
m_doNotActivateOnGameMode = settings.doNotActivateOnGameMode;
m_fadeDuration = settings.animationDurationMs > 0 ? settings.animationDurationMs : 1;
m_finalAlphaNumerator = settings.overlayOpacity;
m_sonarZoomFactor = settings.spotlightInitialZoom;
}
else
{
// Runtime objects already created. Should update in the owner thread.
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
FindMyMouseSettings localSettings = settings;
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
if (!m_destroyed)
{
// Runtime objects not created yet. Just update fields.
m_sonarRadius = localSettings.spotlightRadius;
m_sonarRadiusFloat = static_cast<float>(m_sonarRadius);
m_backgroundColor = localSettings.backgroundColor;
m_spotlightColor = localSettings.spotlightColor;
m_doNotActivateOnGameMode = localSettings.doNotActivateOnGameMode;
m_fadeDuration = localSettings.animationDurationMs > 0 ? localSettings.animationDurationMs : 1;
m_finalAlphaNumerator = localSettings.overlayOpacity;
m_sonarZoomFactor = localSettings.spotlightInitialZoom;
// Apply new settings to runtime composition objects.
m_backdrop.Brush().as<winrt::CompositionColorBrush>().Color(m_backgroundColor);
m_circleShape.FillBrush().as<winrt::CompositionColorBrush>().Color(m_spotlightColor);
m_circleShape.Offset({ m_sonarRadiusFloat * m_sonarZoomFactor, m_sonarRadiusFloat * m_sonarZoomFactor });
m_spotlight.Size({ m_sonarRadiusFloat * 2 * m_sonarZoomFactor, m_sonarRadiusFloat * 2 * m_sonarZoomFactor });
m_animation.Duration(std::chrono::milliseconds{ m_fadeDuration });
m_circleGeometry.StopAnimation(L"Radius");
// Update animation
auto radiusExpression = m_compositor.CreateExpressionAnimation();
radiusExpression.SetReferenceParameter(L"Root", m_root);
wchar_t expressionText[256];
winrt::check_hresult(StringCchPrintfW(expressionText, ARRAYSIZE(expressionText), L"Lerp(Vector2(%d, %d), Vector2(%d, %d), Root.Opacity * %d / %d)", m_sonarRadius * m_sonarZoomFactor, m_sonarRadius * m_sonarZoomFactor, m_sonarRadius, m_sonarRadius, FinalAlphaDenominator, m_finalAlphaNumerator));
radiusExpression.Expression(expressionText);
m_circleGeometry.StartAnimation(L"Radius", radiusExpression);
}
});
if (!enqueueSucceeded)
{
Logger::error("Couldn't enqueue message to update the sonar settings.");
}
}
}
private:
winrt::Compositor m_compositor{ nullptr };
winrt::Desktop::DesktopWindowTarget m_target{ nullptr };
@ -588,6 +645,11 @@ private:
winrt::CompositionEllipseGeometry m_circleGeometry{ nullptr };
winrt::ShapeVisual m_spotlight{ nullptr };
winrt::CompositionCommitBatch m_batch{ nullptr };
winrt::SpriteVisual m_backdrop{ nullptr };
winrt::CompositionSpriteShape m_circleShape{ nullptr };
winrt::Windows::UI::Color m_backgroundColor = FIND_MY_MOUSE_DEFAULT_BACKGROUND_COLOR;
winrt::Windows::UI::Color m_spotlightColor = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_COLOR;
winrt::ScalarKeyFrameAnimation m_animation{ nullptr };
};
template<typename D>
@ -631,7 +693,7 @@ struct GdiSonar : SuperSonar<D>
void OnFadeTimer()
{
auto now = GetTickCount();
auto step = (int)((now - m_fadeStart) * MaxAlpha / this->FadeDuration);
auto step = (int)((now - m_fadeStart) * MaxAlpha / this->m_fadeDuration);
this->Shim()->InvalidateSonar();
if (m_alpha < m_alphaTarget)
@ -666,13 +728,13 @@ protected:
int CurrentSonarRadius()
{
int range = MaxAlpha - m_alpha;
int radius = this->SonarRadius + this->SonarRadius * range * (this->SonarZoomFactor - 1) / MaxAlpha;
int radius = this->m_sonarRadius + this->m_sonarRadius * range * (this->m_sonarZoomFactor - 1) / MaxAlpha;
return radius;
}
private:
static constexpr DWORD FadeFramePeriod = 10;
static constexpr int MaxAlpha = SuperSonar<D>::FinalAlphaNumerator * 255 / SuperSonar<D>::FinalAlphaDenominator;
int MaxAlpha = SuperSonar<D>::m_finalAlphaNumerator * 255 / SuperSonar<D>::FinalAlphaDenominator;
static constexpr DWORD TIMER_ID_FADE = 101;
private:
@ -792,6 +854,14 @@ struct GdiCrosshairs : GdiSonar<GdiCrosshairs>
#pragma region Super_Sonar_API
CompositionSpotlight* m_sonar = nullptr;
void FindMyMouseApplySettings(const FindMyMouseSettings& settings)
{
if (m_sonar != nullptr)
{
Logger::info("Applying settings.");
m_sonar->ApplySettings(settings, true);
}
}
void FindMyMouseDisable()
{
@ -807,13 +877,8 @@ bool FindMyMouseIsEnabled()
return (m_sonar != nullptr);
}
void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate)
{
m_doNotActivateOnGameMode = doNotActivate;
}
// Based on SuperSonar's original wWinMain.
int FindMyMouseMain(HINSTANCE hinst)
int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings)
{
Logger::info("Starting a sonar instance.");
if (m_sonar != nullptr)
@ -823,6 +888,7 @@ int FindMyMouseMain(HINSTANCE hinst)
}
CompositionSpotlight sonar;
sonar.ApplySettings(settings, false);
if (!sonar.Initialize(hinst))
{
Logger::error("Couldn't initialize a sonar instance.");

View file

@ -1,6 +1,26 @@
#pragma once
#include "pch.h"
int FindMyMouseMain(HINSTANCE hinst);
constexpr bool FIND_MY_MOUSE_DEFAULT_DO_NOT_ACTIVATE_ON_GAME_MODE = true;
const winrt::Windows::UI::Color FIND_MY_MOUSE_DEFAULT_BACKGROUND_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(255, 0, 0, 0);
const winrt::Windows::UI::Color FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(255, 255, 255, 255);
constexpr int FIND_MY_MOUSE_DEFAULT_OVERLAY_OPACITY = 50;
constexpr int FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_RADIUS = 100;
constexpr int FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS = 500;
constexpr int FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM = 9;
struct FindMyMouseSettings
{
bool doNotActivateOnGameMode = FIND_MY_MOUSE_DEFAULT_DO_NOT_ACTIVATE_ON_GAME_MODE;
winrt::Windows::UI::Color backgroundColor = FIND_MY_MOUSE_DEFAULT_BACKGROUND_COLOR;
winrt::Windows::UI::Color spotlightColor = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_COLOR;
int overlayOpacity = FIND_MY_MOUSE_DEFAULT_OVERLAY_OPACITY;
int spotlightRadius = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_RADIUS;
int animationDurationMs = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS;
int spotlightInitialZoom = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM;
};
int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings);
void FindMyMouseDisable();
bool FindMyMouseIsEnabled();
void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate);
void FindMyMouseApplySettings(const FindMyMouseSettings& settings);

View file

@ -5,13 +5,19 @@
#include "FindMyMouse.h"
#include <thread>
#include <common/utils/logger_helper.h>
#include <common/utils/color.h>
namespace
{
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
const wchar_t JSON_KEY_VALUE[] = L"value";
const wchar_t JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE[] = L"do_not_activate_on_game_mode";
const wchar_t JSON_KEY_BACKGROUND_COLOR[] = L"background_color";
const wchar_t JSON_KEY_SPOTLIGHT_COLOR[] = L"spotlight_color";
const wchar_t JSON_KEY_OVERLAY_OPACITY[] = L"overlay_opacity";
const wchar_t JSON_KEY_SPOTLIGHT_RADIUS[] = L"spotlight_radius";
const wchar_t JSON_KEY_ANIMATION_DURATION_MS[] = L"animation_duration_ms";
const wchar_t JSON_KEY_SPOTLIGHT_INITIAL_ZOOM[] = L"spotlight_initial_zoom";
}
extern "C" IMAGE_DOS_HEADER __ImageBase;
@ -48,6 +54,9 @@ private:
// The PowerToy state.
bool m_enabled = false;
// Find My Mouse specific settings
FindMyMouseSettings m_findMyMouseSettings;
// Load initial settings from the persisted values.
void init_settings();
@ -109,7 +118,7 @@ public:
parse_settings(values);
values.save_to_settings_file();
FindMyMouseApplySettings(m_findMyMouseSettings);
}
catch (std::exception&)
{
@ -122,7 +131,7 @@ public:
{
m_enabled = true;
Trace::EnableFindMyMouse(true);
std::thread([]() { FindMyMouseMain(m_hModule); }).detach();
std::thread([=]() { FindMyMouseMain(m_hModule, m_findMyMouseSettings); }).detach();
}
// Disable the powertoy
@ -158,25 +167,103 @@ void FindMyMouse::init_settings()
void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
FindMyMouseSetDoNotActivateOnGameMode(true);
auto settingsObject = settings.get_raw_json();
FindMyMouseSettings findMyMouseSettings;
if (settingsObject.GetView().Size())
{
try
{
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE);
FindMyMouseSetDoNotActivateOnGameMode((bool)jsonPropertiesObject.GetNamedBoolean(JSON_KEY_VALUE));
findMyMouseSettings.doNotActivateOnGameMode = (bool)jsonPropertiesObject.GetNamedBoolean(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to get 'do not activate on game mode' setting");
}
try
{
// Parse background color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_BACKGROUND_COLOR);
auto backgroundColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
uint8_t r, g, b;
if (!checkValidRGB(backgroundColor, &r, &g, &b))
{
Logger::error("Background color RGB value is invalid. Will use default value");
}
else
{
findMyMouseSettings.backgroundColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
}
}
catch (...)
{
Logger::warn("Failed to initialize background color from settings. Will use default value");
}
try
{
// Parse spotlight color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SPOTLIGHT_COLOR);
auto spotlightColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
uint8_t r, g, b;
if (!checkValidRGB(spotlightColor, &r, &g, &b))
{
Logger::error("Spotlight color RGB value is invalid. Will use default value");
}
else
{
findMyMouseSettings.spotlightColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
}
}
catch (...)
{
Logger::warn("Failed to initialize spotlight color from settings. Will use default value");
}
try
{
// Parse Overlay Opacity
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_OVERLAY_OPACITY);
findMyMouseSettings.overlayOpacity = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Overlay Opacity from settings. Will use default value");
}
try
{
// Parse Spotlight Radius
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SPOTLIGHT_RADIUS);
findMyMouseSettings.spotlightRadius = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Spotlight Radius from settings. Will use default value");
}
try
{
// Parse Animation Duration
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ANIMATION_DURATION_MS);
findMyMouseSettings.animationDurationMs = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Animation Duration from settings. Will use default value");
}
try
{
// Parse Spotlight Initial Zoom
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SPOTLIGHT_INITIAL_ZOOM);
findMyMouseSettings.spotlightInitialZoom = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Spotlight Initial Zoom from settings. Will use default value");
}
}
else
{
Logger::info("Find My Mouse settings are empty");
}
m_findMyMouseSettings = findMyMouseSettings;
}

View file

@ -3,6 +3,7 @@
#include <common/SettingsAPI/settings_objects.h>
#include "trace.h"
#include "MouseHighlighter.h"
#include "common/utils/color.h"
namespace
{
@ -57,26 +58,6 @@ private:
// Mouse Highlighter specific settings
MouseHighlighterSettings m_highlightSettings;
// helper function to get the RGB from a #FFFFFF string.
bool checkValidRGB(std::wstring_view hex, uint8_t* R, uint8_t* G, uint8_t* B)
{
if (hex.length() != 7)
return false;
hex = hex.substr(1, 6); // remove #
for (auto& c : hex)
{
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')))
{
return false;
}
}
if (swscanf_s(hex.data(), L"%2hhx%2hhx%2hhx", R, G, B) != 3)
{
return false;
}
return true;
}
public:
// Constructor
MouseHighlighter()

View file

@ -291,7 +291,7 @@ namespace ColorPicker.Controls
var newValue = (sender as TextBox).Text;
// support hex with 3 and 6 characters
var reg = new Regex("^#([0-9A-F]{3}){1,2}$");
var reg = new Regex("^#([0-9A-Fa-f]{3}){1,2}$");
if (!reg.IsMatch(newValue))
{

View file

@ -44,6 +44,14 @@ namespace ColorPicker.Helpers
return (cyan, magenta, yellow, blackKey);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a float color styling(0.1f, 0.1f, 0.1f)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The int / 255d for each value to get value between 0 and 1</returns>
internal static (double red, double green, double blue) ConvertToDouble(Color color)
=> (color.R / 255d, color.G / 255d, color.B / 255d);
/// <summary>
/// Convert a given <see cref="Color"/> to a HSB color (hue, saturation, brightness)
/// </summary>

View file

@ -46,6 +46,8 @@ namespace ColorPicker.Helpers
ColorRepresentationType.RGB => ColorToRGB(color),
ColorRepresentationType.CIELAB => ColorToCIELAB(color),
ColorRepresentationType.CIEXYZ => ColorToCIEXYZ(color),
ColorRepresentationType.VEC4 => ColorToFloat(color),
ColorRepresentationType.DecimalValue => ColorToDecimal(color),
// Fall-back value, when "_userSettings.CopiedColorRepresentation.Value" is incorrect
_ => ColorToHex(color),
@ -99,6 +101,29 @@ namespace ColorPicker.Helpers
+ $", {brightness.ToString(CultureInfo.InvariantCulture)}%)";
}
/// <summary>
/// Return a <see cref="string"/> representation float color styling(0.1f, 0.1f, 0.1f)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>a string value (0.1f, 0.1f, 0.1f)</returns>
private static string ColorToFloat(Color color)
{
var (red, green, blue) = ColorHelper.ConvertToDouble(color);
var precision = 2;
return $"({Math.Round(red, precision).ToString("0.##", CultureInfo.InvariantCulture)}f, {Math.Round(green, precision).ToString("0.##", CultureInfo.InvariantCulture)}f, {Math.Round(blue, precision).ToString("0.##", CultureInfo.InvariantCulture)}f, 1f)";
}
/// <summary>
/// Return a <see cref="string"/> representation decimal color value
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>a string value number</returns>
private static string ColorToDecimal(Color color)
{
return $"{color.R + (color.G * 256) + (color.B * 65536)}";
}
/// <summary>
/// Return a <see cref="string"/> representation of a HSI color
/// </summary>

View file

@ -216,6 +216,18 @@ namespace ColorPicker.ViewModels
FormatName = ColorRepresentationType.CIEXYZ.ToString(),
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CIEXYZ); },
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.VEC4.ToString(),
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.VEC4); },
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = "Decimal",
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.DecimalValue); },
});
_userSettings.VisibleColorFormats.CollectionChanged += VisibleColorFormats_CollectionChanged;

View file

@ -24,6 +24,8 @@ namespace Microsoft.ColorPicker.UnitTests
[DataRow(ColorRepresentationType.RGB, "rgb(0, 0, 0)")]
[DataRow(ColorRepresentationType.CIELAB, "CIELab(0, 0, 0)")]
[DataRow(ColorRepresentationType.CIEXYZ, "xyz(0, 0, 0)")]
[DataRow(ColorRepresentationType.VEC4, "(0f, 0f, 0f, 1f)")]
[DataRow(ColorRepresentationType.DecimalValue, "0")]
public void GetStringRepresentationTest(ColorRepresentationType type, string expected)
{

View file

@ -25,9 +25,8 @@ const std::wstring instanceMutexName = L"Local\\PowerToys_FancyZones_InstanceMut
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ int nCmdShow)
{
winrt::init_apartment();
InitUnhandledExceptionHandler_x64();
LoggerHelpers::init_logger(moduleName, internalPath, LogSettings::fancyZonesLoggerName);
InitUnhandledExceptionHandler_x64();
auto mutex = CreateMutex(nullptr, true, instanceMutexName.c_str());
if (mutex == nullptr)

View file

@ -61,7 +61,7 @@
<ClInclude Include="ZoneColors.h" />
<ClInclude Include="ZoneSet.h" />
<ClInclude Include="WorkArea.h" />
<ClInclude Include="ZoneWindowDrawing.h" />
<ClInclude Include="ZonesOverlay.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="FancyZones.cpp" />
@ -84,7 +84,7 @@
<ClCompile Include="Zone.cpp" />
<ClCompile Include="ZoneSet.cpp" />
<ClCompile Include="WorkArea.cpp" />
<ClCompile Include="ZoneWindowDrawing.cpp" />
<ClCompile Include="ZonesOverlay.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="fancyzones.base.rc" />

View file

@ -75,7 +75,7 @@
<ClInclude Include="KeyState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZoneWindowDrawing.h">
<ClInclude Include="ZonesOverlay.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MonitorUtils.h">
@ -140,7 +140,7 @@
<ClCompile Include="FancyZonesDataTypes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZoneWindowDrawing.cpp">
<ClCompile Include="ZonesOverlay.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="OnThreadExecutor.cpp">

View file

@ -101,12 +101,12 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
{
for (auto [keyMonitor, workArea] : workAreaMap)
{
// Skip calling ShowZoneWindow for iter->second (m_draggedWindowWorkArea) since it
// Skip calling ShowZonesOverlay for iter->second (m_draggedWindowWorkArea) since it
// was already called in MoveSizeEnter
const bool moveSizeEnterCalled = workArea == m_draggedWindowWorkArea;
if (workArea && !moveSizeEnterCalled)
{
workArea->ShowZoneWindow();
workArea->ShowZonesOverlay();
}
}
}
@ -119,7 +119,7 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
{
if (workArea)
{
workArea->HideZoneWindow();
workArea->HideZonesOverlay();
}
}
}
@ -159,7 +159,7 @@ void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen,
{
if (workArea)
{
workArea->HideZoneWindow();
workArea->HideZonesOverlay();
}
}
}
@ -174,7 +174,7 @@ void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen,
m_draggedWindowWorkArea->ClearSelectedZones();
if (!m_settings->GetSettings()->showZonesOnAllMonitors)
{
m_draggedWindowWorkArea->HideZoneWindow();
m_draggedWindowWorkArea->HideZonesOverlay();
}
m_draggedWindowWorkArea = iter->second;
@ -279,7 +279,7 @@ void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const st
{
if (workArea)
{
workArea->HideZoneWindow();
workArea->HideZonesOverlay();
}
}
}

View file

@ -6,7 +6,7 @@
#include "FancyZonesData.h"
#include "FancyZonesDataTypes.h"
#include "ZoneWindowDrawing.h"
#include "ZonesOverlay.h"
#include "trace.h"
#include "util.h"
#include "on_thread_executor.h"
@ -21,7 +21,7 @@
// Non-Localizable strings
namespace NonLocalizable
{
const wchar_t ToolWindowClassName[] = L"SuperFancyZones_ZoneWindow";
const wchar_t ToolWindowClassName[] = L"FancyZones_ZonesOverlay";
}
using namespace FancyZonesUtils;
@ -57,13 +57,13 @@ namespace
public:
HWND NewZoneWindow(Rect position, HINSTANCE hinstance, WorkArea* owner)
HWND NewZonesOverlayWindow(Rect position, HINSTANCE hinstance, WorkArea* owner)
{
HWND windowFromPool = ExtractWindow();
if (windowFromPool == NULL)
{
HWND window = CreateWindowExW(WS_EX_TOOLWINDOW, NonLocalizable::ToolWindowClassName, L"", WS_POPUP, position.left(), position.top(), position.width(), position.height(), nullptr, nullptr, hinstance, owner);
Logger::info("Creating new zone window, hWnd = {}", (void*)window);
Logger::info("Creating new ZonesOverlay window, hWnd = {}", (void*)window);
MakeWindowTransparent(window);
// According to ShowWindow docs, we must call it with SW_SHOWNORMAL the first time
@ -73,17 +73,17 @@ namespace
}
else
{
Logger::info("Reusing zone window from pool, hWnd = {}", (void*)windowFromPool);
Logger::info("Reusing ZonesOverlay window from pool, hWnd = {}", (void*)windowFromPool);
SetWindowLongPtrW(windowFromPool, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(owner));
MoveWindow(windowFromPool, position.left(), position.top(), position.width(), position.height(), TRUE);
return windowFromPool;
}
}
void FreeZoneWindow(HWND window)
void FreeZonesOverlayWindow(HWND window)
{
_TRACER_;
Logger::info("Freeing zone window, hWnd = {}", (void*)window);
Logger::info("Freeing ZonesOverlay window into pool, hWnd = {}", (void*)window);
SetWindowLongPtrW(window, GWLP_USERDATA, 0);
ShowWindow(window, SW_HIDE);
@ -133,9 +133,9 @@ public:
IFACEMETHODIMP_(ZoneIndexSet)
GetWindowZoneIndexes(HWND window) const noexcept;
IFACEMETHODIMP_(void)
ShowZoneWindow() noexcept;
ShowZonesOverlay() noexcept;
IFACEMETHODIMP_(void)
HideZoneWindow() noexcept;
HideZonesOverlay() noexcept;
IFACEMETHODIMP_(void)
UpdateActiveZoneSet() noexcept;
IFACEMETHODIMP_(void)
@ -169,7 +169,7 @@ private:
ZoneIndexSet m_highlightZone;
WPARAM m_keyLast{};
size_t m_keyCycle{};
std::unique_ptr<ZoneWindowDrawing> m_zoneWindowDrawing;
std::unique_ptr<ZonesOverlay> m_zonesOverlay;
ZoneColors m_zoneColors;
OverlappingZonesAlgorithm m_overlappingAlgorithm;
};
@ -187,7 +187,7 @@ WorkArea::WorkArea(HINSTANCE hinstance)
WorkArea::~WorkArea()
{
windowPool.FreeZoneWindow(m_window);
windowPool.FreeZonesOverlayWindow(m_window);
}
bool WorkArea::Init(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm)
@ -215,14 +215,14 @@ bool WorkArea::Init(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataT
m_uniqueId = uniqueId;
InitializeZoneSets(parentUniqueId);
m_window = windowPool.NewZoneWindow(workAreaRect, hinstance, this);
m_window = windowPool.NewZonesOverlayWindow(workAreaRect, hinstance, this);
if (!m_window)
{
return false;
}
m_zoneWindowDrawing = std::make_unique<ZoneWindowDrawing>(m_window);
m_zonesOverlay = std::make_unique<ZonesOverlay>(m_window);
return true;
}
@ -232,7 +232,7 @@ IFACEMETHODIMP WorkArea::MoveSizeEnter(HWND window) noexcept
m_windowMoveSize = window;
m_highlightZone = {};
m_initialHighlightZone = {};
ShowZoneWindow();
ShowZonesOverlay();
Trace::WorkArea::MoveOrResizeStarted(m_zoneSet);
return S_OK;
}
@ -275,7 +275,7 @@ IFACEMETHODIMP WorkArea::MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled,
if (redraw)
{
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
}
return S_OK;
@ -301,7 +301,7 @@ IFACEMETHODIMP WorkArea::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcep
}
Trace::WorkArea::MoveOrResizeEnd(m_zoneSet);
HideZoneWindow();
HideZonesOverlay();
m_windowMoveSize = nullptr;
return S_OK;
}
@ -400,22 +400,22 @@ WorkArea::GetWindowZoneIndexes(HWND window) const noexcept
}
IFACEMETHODIMP_(void)
WorkArea::ShowZoneWindow() noexcept
WorkArea::ShowZonesOverlay() noexcept
{
if (m_window)
{
SetAsTopmostWindow();
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zoneWindowDrawing->Show();
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zonesOverlay->Show();
}
}
IFACEMETHODIMP_(void)
WorkArea::HideZoneWindow() noexcept
WorkArea::HideZonesOverlay() noexcept
{
if (m_window)
{
m_zoneWindowDrawing->Hide();
m_zonesOverlay->Hide();
m_keyLast = 0;
m_windowMoveSize = nullptr;
m_highlightZone = {};
@ -429,7 +429,7 @@ WorkArea::UpdateActiveZoneSet() noexcept
if (m_window)
{
m_highlightZone.clear();
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
}
}
@ -448,7 +448,7 @@ WorkArea::ClearSelectedZones() noexcept
if (m_highlightZone.size())
{
m_highlightZone.clear();
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
}
}
@ -458,8 +458,8 @@ WorkArea::FlashZones() noexcept
if (m_window)
{
SetAsTopmostWindow();
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), {}, m_zoneColors);
m_zoneWindowDrawing->Flash();
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), {}, m_zoneColors);
m_zonesOverlay->Flash();
}
}

View file

@ -108,8 +108,14 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IWorkArea :
* @returns Zone index of the window
*/
IFACEMETHOD_(ZoneIndexSet, GetWindowZoneIndexes)(HWND window) const = 0;
IFACEMETHOD_(void, ShowZoneWindow)() = 0;
IFACEMETHOD_(void, HideZoneWindow)() = 0;
/**
* Show a drawing of the zones in the work area.
*/
IFACEMETHOD_(void, ShowZonesOverlay)() = 0;
/**
* Hide the drawing of the zones in the work area.
*/
IFACEMETHOD_(void, HideZonesOverlay)() = 0;
/**
* Update currently active zone layout for this work area.
*/

View file

@ -1,5 +1,5 @@
#include "pch.h"
#include "ZoneWindowDrawing.h"
#include "ZonesOverlay.h"
#include <algorithm>
#include <map>
@ -7,7 +7,6 @@
#include <vector>
#include <common/logger/call_tracer.h>
#include <common/logger/logger.h>
namespace
{
@ -20,7 +19,7 @@ namespace NonLocalizable
const wchar_t SegoeUiFont[] = L"Segoe ui";
}
float ZoneWindowDrawing::GetAnimationAlpha()
float ZonesOverlay::GetAnimationAlpha()
{
// Lock is held by the caller
@ -41,7 +40,7 @@ float ZoneWindowDrawing::GetAnimationAlpha()
return std::clamp(millis / FadeInDurationMillis, 0.001f, 1.f);
}
ID2D1Factory* ZoneWindowDrawing::GetD2DFactory()
ID2D1Factory* ZonesOverlay::GetD2DFactory()
{
static auto pD2DFactory = [] {
ID2D1Factory* res = nullptr;
@ -51,7 +50,7 @@ ID2D1Factory* ZoneWindowDrawing::GetD2DFactory()
return pD2DFactory;
}
IDWriteFactory* ZoneWindowDrawing::GetWriteFactory()
IDWriteFactory* ZonesOverlay::GetWriteFactory()
{
static auto pDWriteFactory = [] {
IUnknown* res = nullptr;
@ -61,7 +60,7 @@ IDWriteFactory* ZoneWindowDrawing::GetWriteFactory()
return pDWriteFactory;
}
D2D1_COLOR_F ZoneWindowDrawing::ConvertColor(COLORREF color)
D2D1_COLOR_F ZonesOverlay::ConvertColor(COLORREF color)
{
return D2D1::ColorF(GetRValue(color) / 255.f,
GetGValue(color) / 255.f,
@ -69,12 +68,12 @@ D2D1_COLOR_F ZoneWindowDrawing::ConvertColor(COLORREF color)
1.f);
}
D2D1_RECT_F ZoneWindowDrawing::ConvertRect(RECT rect)
D2D1_RECT_F ZonesOverlay::ConvertRect(RECT rect)
{
return D2D1::RectF((float)rect.left + 0.5f, (float)rect.top + 0.5f, (float)rect.right - 0.5f, (float)rect.bottom - 0.5f);
}
ZoneWindowDrawing::ZoneWindowDrawing(HWND window)
ZonesOverlay::ZonesOverlay(HWND window)
{
HRESULT hr;
m_window = window;
@ -84,7 +83,7 @@ ZoneWindowDrawing::ZoneWindowDrawing(HWND window)
// Obtain the size of the drawing area.
if (!GetClientRect(window, &m_clientRect))
{
Logger::error("couldn't initialize ZoneWindowDrawing: GetClientRect failed");
Logger::error("couldn't initialize ZonesOverlay: GetClientRect failed");
return;
}
@ -103,14 +102,14 @@ ZoneWindowDrawing::ZoneWindowDrawing(HWND window)
if (!SUCCEEDED(hr))
{
Logger::error("couldn't initialize ZoneWindowDrawing: CreateHwndRenderTarget failed with {}", hr);
Logger::error("couldn't initialize ZonesOverlay: CreateHwndRenderTarget failed with {}", hr);
return;
}
m_renderThread = std::thread([this]() { RenderLoop(); });
}
ZoneWindowDrawing::RenderResult ZoneWindowDrawing::Render()
ZonesOverlay::RenderResult ZonesOverlay::Render()
{
std::unique_lock lock(m_mutex);
@ -193,7 +192,7 @@ ZoneWindowDrawing::RenderResult ZoneWindowDrawing::Render()
return RenderResult::Ok;
}
void ZoneWindowDrawing::RenderLoop()
void ZonesOverlay::RenderLoop()
{
while (!m_abortThread)
{
@ -212,7 +211,7 @@ void ZoneWindowDrawing::RenderLoop()
}
}
void ZoneWindowDrawing::Hide()
void ZonesOverlay::Hide()
{
_TRACER_;
bool shouldHideWindow = true;
@ -229,7 +228,7 @@ void ZoneWindowDrawing::Hide()
}
}
void ZoneWindowDrawing::Show()
void ZonesOverlay::Show()
{
_TRACER_;
bool shouldShowWindow = true;
@ -257,7 +256,7 @@ void ZoneWindowDrawing::Show()
m_cv.notify_all();
}
void ZoneWindowDrawing::Flash()
void ZonesOverlay::Flash()
{
_TRACER_;
bool shouldShowWindow = true;
@ -277,9 +276,9 @@ void ZoneWindowDrawing::Flash()
m_cv.notify_all();
}
void ZoneWindowDrawing::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
const ZoneIndexSet& highlightZones,
const ZoneColors& colors)
void ZonesOverlay::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
const ZoneIndexSet& highlightZones,
const ZoneColors& colors)
{
_TRACER_;
std::unique_lock lock(m_mutex);
@ -345,7 +344,7 @@ void ZoneWindowDrawing::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
}
}
ZoneWindowDrawing::~ZoneWindowDrawing()
ZonesOverlay::~ZonesOverlay()
{
{
std::unique_lock lock(m_mutex);

View file

@ -13,7 +13,7 @@
#include "FancyZones.h"
#include "ZoneColors.h"
class ZoneWindowDrawing
class ZonesOverlay
{
struct DrawableRect
{
@ -60,8 +60,8 @@ class ZoneWindowDrawing
public:
~ZoneWindowDrawing();
ZoneWindowDrawing(HWND window);
~ZonesOverlay();
ZonesOverlay(HWND window);
void Hide();
void Show();
void Flash();

View file

@ -615,453 +615,6 @@
</Setter>
</Style>
<Style TargetType="TextBox" x:Key="AutoSuggestBoxTextBoxStyle">
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}" />
<Setter Property="Background" Value="{ThemeResource TextControlBackground}" />
<Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}" />
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextControlSelectionHighlightColor}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="AcceptsReturn" Value="False" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.Resources>
<Style x:Name="DeleteButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="ButtonLayoutGrid"
BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{ThemeResource TextControlButtonBackground}"
Margin="{StaticResource AutoSuggestBoxDeleteButtonMargin}"
contract7Present:CornerRadius="{ThemeResource ControlCornerRadius}"
contract7NotPresent:CornerRadius="{ThemeResource ControlCornerRadius}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ButtonLayoutGrid"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="GlyphElement"
Foreground="{ThemeResource TextControlButtonForeground}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontStyle="Normal"
FontSize="{ThemeResource AutoSuggestBoxIconFontSize}"
Text="&#xE10A;"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
AutomationProperties.AccessibilityView="Raw" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Name="QueryButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter x:Name="ContentPresenter"
Background="{ThemeResource TextControlButtonBackground}"
contract7Present:BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
contract7NotPresent:CornerRadius="{Binding Source={ThemeResource ControlCornerRadius}, Converter={StaticResource RightCornerRadiusFilterConverter}}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
FontSize="{ThemeResource AutoSuggestBoxIconFontSize}"
Margin="{ThemeResource AutoSuggestBoxInnerButtonMargin}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
muxc:AnimatedIcon.State="Normal">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(muxc:AnimatedIcon.State)" Value="PointerOver"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(muxc:AnimatedIcon.State)" Value="Pressed"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderThemeThicknessFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="QueryButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForeground}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="ButtonVisible">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ButtonCollapsed" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="{ThemeResource AutoSuggestBoxRightButtonMargin}" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border x:Name="BorderElement"
Grid.Row="1"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="4"
Grid.RowSpan="1"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
contract7NotPresent:CornerRadius="{ThemeResource ControlCornerRadius}" />
<ContentPresenter x:Name="HeaderContentPresenter"
x:DeferLoadStrategy="Lazy"
Visibility="Collapsed"
Grid.Row="0"
Foreground="{ThemeResource TextControlHeaderForeground}"
Margin="{ThemeResource AutoSuggestBoxTopHeaderMargin}"
Grid.ColumnSpan="4"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="Normal"
TextWrapping="Wrap" />
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
AutomationProperties.AccessibilityView="Raw"
ZoomMode="Disabled" />
<ContentControl x:Name="PlaceholderTextContentPresenter"
Grid.Row="1"
Foreground="{ThemeResource TextControlPlaceholderForeground}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
IsTabStop="False"
Grid.ColumnSpan="4"
Content="{TemplateBinding PlaceholderText}"
IsHitTestVisible="False" />
<Button x:Name="DeleteButton"
Grid.Row="1"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
Style="{StaticResource DeleteButtonStyle}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{ThemeResource HelperButtonThemePadding}"
Margin="0,0,36,0"
IsTabStop="False"
Grid.Column="1"
Visibility="Collapsed"
FontSize="{TemplateBinding FontSize}"
Width="32"
AutomationProperties.AccessibilityView="Raw"
VerticalAlignment="Stretch" />
<Button x:Name="QueryButton"
Grid.Row="1"
Grid.Column="2"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
Style="{StaticResource QueryButtonStyle}"
BorderThickness="{TemplateBinding BorderThickness}"
Margin="2,0,0,0"
Padding="{ThemeResource HelperButtonThemePadding}"
IsTabStop="False"
FontSize="{TemplateBinding FontSize}"
Width="32"
Height="28"
VerticalAlignment="Stretch"
AutomationProperties.AccessibilityView="Raw"/>
<contract7Present:ContentPresenter x:Name="DescriptionPresenter"
Grid.Row="2"
Grid.ColumnSpan="4"
Content="{TemplateBinding Description}"
x:Load="False"
Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}"
AutomationProperties.AccessibilityView="Raw" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="AutoSuggestBox" BasedOn="{StaticResource CustomAutoSuggestBoxStyle}" />
<Style x:Key="CustomAutoSuggestBoxStyle" TargetType="AutoSuggestBox">
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}" />
<Setter Property="Background" Value="{ThemeResource TextControlBackground}" />
<Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="TextBoxStyle" Value="{StaticResource AutoSuggestBoxTextBoxStyle}" />
<!--<contract6Present:Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}" />-->
<Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}" />
<!--<contract7Present:Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />-->
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="primitives:AutoSuggestBoxHelper.KeepInteriorCornersSquare" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="AutoSuggestBox">
<Grid x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Orientation">
<VisualState x:Name="Landscape" />
<VisualState x:Name="Portrait" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox x:Name="TextBox"
Style="{TemplateBinding TextBoxStyle}"
PlaceholderText="{TemplateBinding PlaceholderText}"
Header="{TemplateBinding Header}"
Width="{TemplateBinding Width}"
contract7Present:Description="{TemplateBinding Description}"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
FontSize="{TemplateBinding FontSize}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontStretch="{TemplateBinding FontStretch}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
ScrollViewer.BringIntoViewOnFocusChange="False"
Canvas.ZIndex="0"
Margin="0"
DesiredCandidateWindowAlignment="BottomEdge"
UseSystemFocusVisuals="{TemplateBinding UseSystemFocusVisuals}"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"/>
<Popup x:Name="SuggestionsPopup">
<Border x:Name="SuggestionsContainer"
Padding="{ThemeResource AutoSuggestListMargin}"
BorderThickness="{ThemeResource AutoSuggestListBorderThemeThickness}"
BorderBrush="{ThemeResource AutoSuggestBoxSuggestionsListBorderBrush}"
Background="{ThemeResource AutoSuggestBoxSuggestionsListBackground}"
CornerRadius="{ThemeResource OverlayCornerRadius}">
<Border.RenderTransform>
<contract7NotPresent:TranslateTransform x:Name="UpwardTransform" />
</Border.RenderTransform>
<ListView
x:Name="SuggestionsList"
DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
IsItemClickEnabled="True"
ItemTemplate="{TemplateBinding ItemTemplate}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
MaxHeight="{ThemeResource AutoSuggestListMaxHeight}"
Margin="{ThemeResource AutoSuggestListPadding}">
<ListView.ItemContainerTransitions>
<contract7NotPresent:TransitionCollection />
</ListView.ItemContainerTransitions>
</ListView>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Application.Resources>
</Toolkit:XamlApplication>

View file

@ -64,7 +64,6 @@
IsItemClickEnabled="False"
Grid.ColumnSpan="6"
ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}"
Margin="0,0,0,0"
Grid.Row="1">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
@ -121,17 +120,33 @@
</ListView>
</Grid>
<Grid Grid.Column="0" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid Grid.Column="0" Grid.Row="1" MaxWidth="357" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="48" />
</Grid.RowDefinitions>
<ScrollViewer>
<StackPanel Orientation="Vertical" Padding="0,0,0,16" Margin="0,0,12,0">
<Grid>
<AutoSuggestBox x:Name="textBox_search" x:Uid="SearchBox" Height="40" VerticalContentAlignment="Center" ItemsSource="{x:Bind SearchMRU}" />
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<AutoSuggestBox x:Name="textBox_search" x:Uid="SearchBox" Height="40" VerticalContentAlignment="Center" ItemsSource="{x:Bind SearchMRU}" />
<Button FontFamily="{ThemeResource SymbolThemeFontFamily}" VerticalAlignment="Center" Visibility="{Binding ElementName=checkBox_regex, Path=IsChecked}" MinHeight="32" Margin="4" x:Uid="RegExButton" Background="Transparent" BorderBrush="Transparent" Content="&#xE946;" HorizontalAlignment="Right">
<Button Grid.Column="1"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
VerticalAlignment="Center"
Visibility="{Binding ElementName=checkBox_regex, Path=IsChecked}"
Height="40"
Width="28"
Padding="0"
Margin="0,0,-4,0"
BorderBrush="Transparent"
Background="Transparent"
x:Uid="RegExButton"
Content="&#xE946;"
HorizontalAlignment="Right">
<Button.Flyout>
<Flyout x:Name="RegExFlyout">
<Grid>
@ -153,7 +168,7 @@
<TextBlock FontFamily="Consolas" Foreground="{ThemeResource ButtonForeground}" Text="{x:Bind Code}" />
</Border>
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Margin="0,0,0,0" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
@ -174,9 +189,24 @@
<Rectangle Height="1" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" Margin="0,16,0,20" />
<Grid>
<AutoSuggestBox x:Name="textBox_replace" Margin="0,0,0,0" x:Uid="ReplaceBox" Height="40" VerticalContentAlignment="Center" Padding="12,12,0,0" ItemsSource="{x:Bind ReplaceMRU}" />
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<AutoSuggestBox x:Name="textBox_replace" x:Uid="ReplaceBox" Height="40" VerticalContentAlignment="Center" Padding="12,12,0,0" ItemsSource="{x:Bind ReplaceMRU}" />
<Button FontFamily="{ThemeResource SymbolThemeFontFamily}" VerticalAlignment="Center" MinHeight="32" Margin="4" x:Uid="FileCreationButton" Background="Transparent" BorderBrush="Transparent" Content="&#xE946;" HorizontalAlignment="Right">
<Button FontFamily="{ThemeResource SymbolThemeFontFamily}"
VerticalAlignment="Center"
x:Uid="FileCreationButton"
Grid.Column="1"
Width="28"
Height="40"
Padding="0"
Margin="0,0,-4,0"
BorderBrush="Transparent"
Background="Transparent"
Content="&#xE946;"
HorizontalAlignment="Right">
<Button.Flyout>
<Flyout x:Name="DateTimeFlyout" ShouldConstrainToRootBounds="False">
<Grid>
@ -197,7 +227,7 @@
<TextBlock FontFamily="Consolas" Foreground="{ThemeResource ButtonForeground}" Text="{x:Bind Code}" />
</Border>
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Margin="0,0,0,0" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
@ -237,7 +267,7 @@
<ToggleButton x:Name="toggleButton_enumItems" Content="&#xEA40;" FontFamily="{ThemeResource SymbolThemeFontFamily}" MinHeight="32" x:Uid="ToggleButton_EnumItems" Style="{StaticResource CustomToggleButtonStyle}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
<Rectangle Height="1" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" Margin="0,0,12,0" VerticalAlignment="Top" Grid.Row="1" />

View file

@ -65,5 +65,15 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
/// Color presentation as CIEXYZ color space (X[0..95], Y[0..100], Z[0..109]
/// </summary>
CIEXYZ = 10,
/// <summary>
/// Color presentation as RGB float (red[0..1], green[0..1], blue[0..1])
/// </summary>
VEC4 = 11,
/// <summary>
/// Color presentation as integer decimal value 0-16777215
/// </summary>
DecimalValue = 12,
}
}

View file

@ -11,9 +11,33 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("do_not_activate_on_game_mode")]
public BoolProperty DoNotActivateOnGameMode { get; set; }
[JsonPropertyName("background_color")]
public StringProperty BackgroundColor { get; set; }
[JsonPropertyName("spotlight_color")]
public StringProperty SpotlightColor { get; set; }
[JsonPropertyName("overlay_opacity")]
public IntProperty OverlayOpacity { get; set; }
[JsonPropertyName("spotlight_radius")]
public IntProperty SpotlightRadius { get; set; }
[JsonPropertyName("animation_duration_ms")]
public IntProperty AnimationDurationMs { get; set; }
[JsonPropertyName("spotlight_initial_zoom")]
public IntProperty SpotlightInitialZoom { get; set; }
public FindMyMouseProperties()
{
DoNotActivateOnGameMode = new BoolProperty(true);
BackgroundColor = new StringProperty("#000000");
SpotlightColor = new StringProperty("#FFFFFF");
OverlayOpacity = new IntProperty(50);
SpotlightRadius = new IntProperty(100);
AnimationDurationMs = new IntProperty(500);
SpotlightInitialZoom = new IntProperty(9);
}
}
}

View file

@ -55,6 +55,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
{ ColorRepresentationType.RGB, "RGB - rgb(100, 50, 75)" },
{ ColorRepresentationType.CIELAB, "CIE LAB - CIELab(76, 21, 80)" },
{ ColorRepresentationType.CIEXYZ, "CIE XYZ - xyz(56, 50, 7)" },
{ ColorRepresentationType.VEC4, "VEC4 - (1.0f, 0.7f, 0f, 1f)" },
{ ColorRepresentationType.DecimalValue, "Decimal - 16755200" },
};
GeneralSettingsConfig = settingsRepository.SettingsConfig;
@ -198,6 +200,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
var ncolFormatName = ColorRepresentationType.NCol.ToString();
var cielabFormatName = ColorRepresentationType.CIELAB.ToString();
var ciexyzFormatName = ColorRepresentationType.CIEXYZ.ToString();
var vec4FormatName = ColorRepresentationType.VEC4.ToString();
var decimalFormatName = "Decimal";
formatsUnordered.Add(new ColorFormatModel(hexFormatName, "ef68ff", visibleFormats.ContainsKey(hexFormatName) && visibleFormats[hexFormatName]));
formatsUnordered.Add(new ColorFormatModel(rgbFormatName, "rgb(239, 104, 255)", visibleFormats.ContainsKey(rgbFormatName) && visibleFormats[rgbFormatName]));
@ -210,6 +214,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
formatsUnordered.Add(new ColorFormatModel(ncolFormatName, "R10, 50%, 75%", visibleFormats.ContainsKey(ncolFormatName) && visibleFormats[ncolFormatName]));
formatsUnordered.Add(new ColorFormatModel(cielabFormatName, "CIELab(66, 72, -52)", visibleFormats.ContainsKey(cielabFormatName) && visibleFormats[cielabFormatName]));
formatsUnordered.Add(new ColorFormatModel(ciexyzFormatName, "xyz(59, 35, 98)", visibleFormats.ContainsKey(ciexyzFormatName) && visibleFormats[ciexyzFormatName]));
formatsUnordered.Add(new ColorFormatModel(vec4FormatName, "(0.94f, 0.41f, 1.00f, 1f)", visibleFormats.ContainsKey(vec4FormatName) && visibleFormats[vec4FormatName]));
formatsUnordered.Add(new ColorFormatModel(decimalFormatName, "15689983", visibleFormats.ContainsKey(decimalFormatName) && visibleFormats[decimalFormatName]));
foreach (var storedColorFormat in _colorPickerSettings.Properties.VisibleColorFormats)
{

View file

@ -45,6 +45,17 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
FindMyMouseSettingsConfig = findMyMouseSettingsRepository.SettingsConfig;
_findMyMouseDoNotActivateOnGameMode = FindMyMouseSettingsConfig.Properties.DoNotActivateOnGameMode.Value;
string backgroundColor = FindMyMouseSettingsConfig.Properties.BackgroundColor.Value;
_findMyMouseBackgroundColor = !string.IsNullOrEmpty(backgroundColor) ? backgroundColor : "#000000";
string spotlightColor = FindMyMouseSettingsConfig.Properties.SpotlightColor.Value;
_findMyMouseSpotlightColor = !string.IsNullOrEmpty(spotlightColor) ? spotlightColor : "#FFFFFF";
_findMyMouseOverlayOpacity = FindMyMouseSettingsConfig.Properties.OverlayOpacity.Value;
_findMyMouseSpotlightRadius = FindMyMouseSettingsConfig.Properties.SpotlightRadius.Value;
_findMyMouseAnimationDurationMs = FindMyMouseSettingsConfig.Properties.AnimationDurationMs.Value;
_findMyMouseSpotlightInitialZoom = FindMyMouseSettingsConfig.Properties.SpotlightInitialZoom.Value;
if (mouseHighlighterSettingsRepository == null)
{
throw new ArgumentNullException(nameof(mouseHighlighterSettingsRepository));
@ -104,6 +115,116 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
}
}
public string FindMyMouseBackgroundColor
{
get
{
return _findMyMouseBackgroundColor;
}
set
{
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#000000";
if (!value.Equals(_findMyMouseBackgroundColor, StringComparison.OrdinalIgnoreCase))
{
_findMyMouseBackgroundColor = value;
FindMyMouseSettingsConfig.Properties.BackgroundColor.Value = value;
NotifyFindMyMousePropertyChanged();
}
}
}
public string FindMyMouseSpotlightColor
{
get
{
return _findMyMouseSpotlightColor;
}
set
{
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
if (!value.Equals(_findMyMouseSpotlightColor, StringComparison.OrdinalIgnoreCase))
{
_findMyMouseSpotlightColor = value;
FindMyMouseSettingsConfig.Properties.SpotlightColor.Value = value;
NotifyFindMyMousePropertyChanged();
}
}
}
public int FindMyMouseOverlayOpacity
{
get
{
return _findMyMouseOverlayOpacity;
}
set
{
if (value != _findMyMouseOverlayOpacity)
{
_findMyMouseOverlayOpacity = value;
FindMyMouseSettingsConfig.Properties.OverlayOpacity.Value = value;
NotifyFindMyMousePropertyChanged();
}
}
}
public int FindMyMouseSpotlightRadius
{
get
{
return _findMyMouseSpotlightRadius;
}
set
{
if (value != _findMyMouseSpotlightRadius)
{
_findMyMouseSpotlightRadius = value;
FindMyMouseSettingsConfig.Properties.SpotlightRadius.Value = value;
NotifyFindMyMousePropertyChanged();
}
}
}
public int FindMyMouseAnimationDurationMs
{
get
{
return _findMyMouseAnimationDurationMs;
}
set
{
if (value != _findMyMouseAnimationDurationMs)
{
_findMyMouseAnimationDurationMs = value;
FindMyMouseSettingsConfig.Properties.AnimationDurationMs.Value = value;
NotifyFindMyMousePropertyChanged();
}
}
}
public int FindMyMouseSpotlightInitialZoom
{
get
{
return _findMyMouseSpotlightInitialZoom;
}
set
{
if (value != _findMyMouseSpotlightInitialZoom)
{
_findMyMouseSpotlightInitialZoom = value;
FindMyMouseSettingsConfig.Properties.SpotlightInitialZoom.Value = value;
NotifyFindMyMousePropertyChanged();
}
}
}
public void NotifyFindMyMousePropertyChanged([CallerMemberName] string propertyName = null)
{
OnPropertyChanged(propertyName);
@ -281,6 +402,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
private bool _isFindMyMouseEnabled;
private bool _findMyMouseDoNotActivateOnGameMode;
private string _findMyMouseBackgroundColor;
private string _findMyMouseSpotlightColor;
private int _findMyMouseOverlayOpacity;
private int _findMyMouseSpotlightRadius;
private int _findMyMouseAnimationDurationMs;
private int _findMyMouseSpotlightInitialZoom;
private bool _isMouseHighlighterEnabled;
private string _highlighterLeftButtonClickColor;

View file

@ -1002,6 +1002,9 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
<data name="FileExplorerPreview_AffectsAllUsers.Title" xml:space="preserve">
<value>The settings on this page affect all users on the system</value>
</data>
<data name="FileExplorerPreview_TogglePreviewPane.Text" xml:space="preserve">
<value>Please ensure that Preview Pane is open by toggling the view with Alt + P in File Explorer</value>
</data>
<data name="FileExplorerPreview_RebootRequired.Title" xml:space="preserve">
<value>A reboot may be required for changes to these settings to take effect</value>
</data>
@ -1733,6 +1736,30 @@ From there, simply click on a Markdown file, PDF file or SVG icon in the File Ex
<value>Do not activate when Game Mode is on</value>
<comment>"Game mode" is the Windows feature to prevent notification when playing a game.</comment>
</data>
<data name="MouseUtils_FindMyMouse_BackgroundColor.Header" xml:space="preserve">
<value>Background color</value>
</data>
<data name="MouseUtils_FindMyMouse_SpotlightColor.Header" xml:space="preserve">
<value>Spotlight color</value>
</data>
<data name="MouseUtils_FindMyMouse_OverlayOpacity.Header" xml:space="preserve">
<value>Overlay opacity</value>
</data>
<data name="MouseUtils_FindMyMouse_SpotlightRadius.Header" xml:space="preserve">
<value>Spotlight radius</value>
</data>
<data name="MouseUtils_FindMyMouse_SpotlightInitialZoom.Header" xml:space="preserve">
<value>Spotlight initial zoom</value>
</data>
<data name="MouseUtils_FindMyMouse_SpotlightInitialZoom.Description" xml:space="preserve">
<value>Spotlight zoom factor at animation start</value>
</data>
<data name="MouseUtils_FindMyMouse_AnimationDurationMs.Header" xml:space="preserve">
<value>Animation duration</value>
</data>
<data name="MouseUtils_FindMyMouse_AnimationDurationMs.Description" xml:space="preserve">
<value>How long it takes for the spotlight to appear/disappear (in ms)</value>
</data>
<data name="MouseUtils_MouseHighlighter.Header" xml:space="preserve">
<value>Mouse Highlighter</value>
<comment>Refers to the utility name</comment>
@ -1745,7 +1772,6 @@ From there, simply click on a Markdown file, PDF file or SVG icon in the File Ex
<value>Mouse Highlighter mode will highlight mouse clicks.</value>
<comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment>
</data>
<data name="MouseUtils_MouseHighlighter_ActivationShortcut.Header" xml:space="preserve">
<value>Activation shortcut</value>
</data>
@ -1753,7 +1779,6 @@ From there, simply click on a Markdown file, PDF file or SVG icon in the File Ex
<value>Customize the shortcut to turn on or off this mode</value>
<comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment>
</data>
<data name="MouseUtils_MouseHighlighter_LeftButtonClickColor.Header" xml:space="preserve">
<value>Left button highlight color</value>
</data>

View file

@ -15,25 +15,79 @@
<StackPanel Orientation="Vertical">
<controls:SettingsGroup x:Uid="MouseUtils_FindMyMouse">
<TextBlock x:Uid="MouseUtils_FindMyMouse_Description" Margin="0,0,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<controls:SettingExpander IsExpanded="True">
<controls:Setting x:Uid="MouseUtils_Enable_FindMyMouse">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFindMyMouse.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:SettingExpander IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}" IsExpanded="False" >
<controls:SettingExpander.Header>
<controls:Setting x:Uid="MouseUtils_Enable_FindMyMouse">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFindMyMouse.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="ShortcutGuide_Appearance_Behavior" Icon="&#xE790;" />
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<CheckBox x:Uid="MouseUtils_Prevent_Activation_On_Game_Mode"
IsChecked="{x:Bind ViewModel.FindMyMouseDoNotActivateOnGameMode, Mode=TwoWay}"
Margin="{StaticResource ExpanderSettingMargin}"
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}" />
<StackPanel>
<CheckBox x:Uid="MouseUtils_Prevent_Activation_On_Game_Mode"
IsChecked="{x:Bind ViewModel.FindMyMouseDoNotActivateOnGameMode, Mode=TwoWay}"
Margin="{StaticResource ExpanderSettingMargin}"
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}" />
<controls:Setting x:Uid="MouseUtils_FindMyMouse_OverlayOpacity" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsFindMyMouseEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<Slider Minimum="1"
Maximum="100"
MinWidth="{StaticResource SettingActionControlMinWidth}"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.FindMyMouseOverlayOpacity}"
HorizontalAlignment="Right"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="MouseUtils_FindMyMouse_BackgroundColor" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsFindMyMouseEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.FindMyMouseBackgroundColor, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="MouseUtils_FindMyMouse_SpotlightColor" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsFindMyMouseEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.FindMyMouseSpotlightColor, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="MouseUtils_FindMyMouse_SpotlightRadius" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsFindMyMouseEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<muxc:NumberBox Minimum="5"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.FindMyMouseSpotlightRadius}"
MinWidth="{StaticResource SettingActionControlMinWidth}"
SpinButtonPlacementMode="Compact"
HorizontalAlignment="Left"
SmallChange="1"
LargeChange="10"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="MouseUtils_FindMyMouse_SpotlightInitialZoom" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsFindMyMouseEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<Slider Minimum="1"
Maximum="40"
MinWidth="{StaticResource SettingActionControlMinWidth}"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.FindMyMouseSpotlightInitialZoom}"
HorizontalAlignment="Right"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="MouseUtils_FindMyMouse_AnimationDurationMs" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsFindMyMouseEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<muxc:NumberBox Minimum="0"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.FindMyMouseAnimationDurationMs}"
MinWidth="{StaticResource SettingActionControlMinWidth}"
SpinButtonPlacementMode="Compact"
HorizontalAlignment="Left"
SmallChange="10"
LargeChange="100"/>
</controls:Setting.ActionContent>
</controls:Setting>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="MouseUtils_MouseHighlighter">
<TextBlock x:Uid="MouseUtils_MouseHighlighter_Description" Margin="0,0,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<controls:Setting x:Uid="MouseUtils_Enable_MouseHighlighter">
@ -53,7 +107,7 @@
</controls:Setting.ActionContent>
</controls:Setting>
<controls:SettingExpander IsEnabled="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=OneWay}" IsExpanded="True" >
<controls:SettingExpander IsEnabled="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=OneWay}" IsExpanded="False" >
<controls:SettingExpander.Header>
<controls:Setting x:Uid="ShortcutGuide_Appearance_Behavior" Icon="&#xE790;" />
</controls:SettingExpander.Header>

View file

@ -35,6 +35,7 @@
/>
<controls:SettingsGroup x:Uid="FileExplorerPreview_PreviewPane_GroupSettings">
<TextBlock x:Uid="FileExplorerPreview_TogglePreviewPane" Margin="0,0,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_Preview_SVG" Icon="&#xE91B;">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.SVGRenderIsEnabled}"

View file

@ -74,7 +74,7 @@ int GetHighlightedZoneIdx(const std::vector<RECT>& zones, const POINT& cursorPos
return -1;
}
void ShowZoneWindow()
void ShowZonesOverlay()
{
// InvalidateRect will essentially send WM_PAINT to main window.
UINT flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE;
@ -86,7 +86,7 @@ void ShowZoneWindow()
} }.detach();
}
void HideZoneWindow()
void HideZonesOverlay()
{
highlighted = std::vector<bool>(ZONE_COUNT, false);
ShowWindow(mainWindow, SW_HIDE);
@ -114,7 +114,7 @@ void RefreshMainWindow()
highlighted = std::vector<bool>(ZONE_COUNT, false);
highlighted[idx] = true;
ShowZoneWindow();
ShowZonesOverlay();
}
}
}
@ -138,11 +138,11 @@ LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
showZoneLayout = !showZoneLayout;
if (showZoneLayout)
{
ShowZoneWindow();
ShowZonesOverlay();
}
else
{
HideZoneWindow();
HideZonesOverlay();
}
return 1;
}