[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
This commit is contained in:
parent
8afac77841
commit
46244e8e84
|
@ -262,6 +262,7 @@ EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643-4663-475E-B329-03F0C9918D48}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643-4663-475E-B329-03F0C9918D48}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
src\common\utils\appMutex.h = src\common\utils\appMutex.h
|
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\com_object_factory.h = src\common\utils\com_object_factory.h
|
||||||
src\common\utils\elevation.h = src\common\utils\elevation.h
|
src\common\utils\elevation.h = src\common\utils\elevation.h
|
||||||
src\common\utils\EventLocker.h = src\common\utils\EventLocker.h
|
src\common\utils\EventLocker.h = src\common\utils\EventLocker.h
|
||||||
|
|
21
src/common/utils/color.h
Normal file
21
src/common/utils/color.h
Normal 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;
|
||||||
|
}
|
|
@ -19,8 +19,6 @@ namespace ABI
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool m_doNotActivateOnGameMode = true;
|
|
||||||
|
|
||||||
#pragma region Super_Sonar_Base_Code
|
#pragma region Super_Sonar_Base_Code
|
||||||
|
|
||||||
template<typename D>
|
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.
|
// 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 const int MIN_DOUBLE_CLICK_TIME = 100;
|
||||||
|
|
||||||
static constexpr int SonarRadius = 100;
|
bool m_destroyed = false;
|
||||||
static constexpr int SonarZoomFactor = 9;
|
bool m_doNotActivateOnGameMode = true;
|
||||||
static constexpr DWORD FadeDuration = 500;
|
int m_sonarRadius = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_RADIUS;
|
||||||
static constexpr int FinalAlphaNumerator = 1;
|
int m_sonarZoomFactor = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM;
|
||||||
static constexpr int FinalAlphaDenominator = 2;
|
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 };
|
winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -150,6 +150,7 @@ void SuperSonar<D>::Terminate()
|
||||||
{
|
{
|
||||||
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
|
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
|
||||||
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
|
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
|
||||||
|
m_destroyed = true;
|
||||||
DestroyWindow(m_hwndOwner);
|
DestroyWindow(m_hwndOwner);
|
||||||
});
|
});
|
||||||
if (!enqueueSucceeded)
|
if (!enqueueSucceeded)
|
||||||
|
@ -457,7 +458,7 @@ void SuperSonar<D>::UpdateMouseSnooping()
|
||||||
struct CompositionSpotlight : SuperSonar<CompositionSpotlight>
|
struct CompositionSpotlight : SuperSonar<CompositionSpotlight>
|
||||||
{
|
{
|
||||||
static constexpr UINT WM_OPACITY_ANIMATION_COMPLETED = WM_APP;
|
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()
|
DWORD GetExtendedStyle()
|
||||||
{
|
{
|
||||||
|
@ -489,7 +490,7 @@ struct CompositionSpotlight : SuperSonar<CompositionSpotlight>
|
||||||
m_batch.Completed([hwnd = m_hwnd](auto&&, auto&&) {
|
m_batch.Completed([hwnd = m_hwnd](auto&&, auto&&) {
|
||||||
PostMessage(hwnd, WM_OPACITY_ANIMATION_COMPLETED, 0, 0);
|
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)
|
if (visible)
|
||||||
{
|
{
|
||||||
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
|
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
|
||||||
|
@ -531,38 +532,38 @@ private:
|
||||||
layer.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
|
layer.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
|
||||||
m_root.Children().InsertAtTop(layer);
|
m_root.Children().InsertAtTop(layer);
|
||||||
|
|
||||||
auto backdrop = m_compositor.CreateSpriteVisual();
|
m_backdrop = m_compositor.CreateSpriteVisual();
|
||||||
backdrop.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
|
m_backdrop.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
|
||||||
backdrop.Brush(m_compositor.CreateColorBrush({ 255, 0, 0, 0 }));
|
m_backdrop.Brush(m_compositor.CreateColorBrush(m_backgroundColor));
|
||||||
layer.Children().InsertAtTop(backdrop);
|
layer.Children().InsertAtTop(m_backdrop);
|
||||||
|
|
||||||
m_circleGeometry = m_compositor.CreateEllipseGeometry(); // radius set via expression animation
|
m_circleGeometry = m_compositor.CreateEllipseGeometry(); // radius set via expression animation
|
||||||
auto circleShape = m_compositor.CreateSpriteShape(m_circleGeometry);
|
m_circleShape = m_compositor.CreateSpriteShape(m_circleGeometry);
|
||||||
circleShape.FillBrush(m_compositor.CreateColorBrush({ 255, 255, 255, 255 }));
|
m_circleShape.FillBrush(m_compositor.CreateColorBrush(m_spotlightColor));
|
||||||
circleShape.Offset({ SonarRadiusFloat * SonarZoomFactor, SonarRadiusFloat * SonarZoomFactor });
|
m_circleShape.Offset({ m_sonarRadiusFloat * m_sonarZoomFactor, m_sonarRadiusFloat * m_sonarZoomFactor });
|
||||||
m_spotlight = m_compositor.CreateShapeVisual();
|
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.AnchorPoint({ 0.5f, 0.5f });
|
||||||
m_spotlight.Shapes().Append(circleShape);
|
m_spotlight.Shapes().Append(m_circleShape);
|
||||||
|
|
||||||
layer.Children().InsertAtTop(m_spotlight);
|
layer.Children().InsertAtTop(m_spotlight);
|
||||||
|
|
||||||
// Implicitly animate the alpha.
|
// Implicitly animate the alpha.
|
||||||
auto animation = m_compositor.CreateScalarKeyFrameAnimation();
|
m_animation = m_compositor.CreateScalarKeyFrameAnimation();
|
||||||
animation.Target(L"Opacity");
|
m_animation.Target(L"Opacity");
|
||||||
animation.InsertExpressionKeyFrame(1.0f, L"this.FinalValue");
|
m_animation.InsertExpressionKeyFrame(1.0f, L"this.FinalValue");
|
||||||
animation.Duration(std::chrono::milliseconds{ FadeDuration });
|
m_animation.Duration(std::chrono::milliseconds{ m_fadeDuration });
|
||||||
auto collection = m_compositor.CreateImplicitAnimationCollection();
|
auto collection = m_compositor.CreateImplicitAnimationCollection();
|
||||||
collection.Insert(L"Opacity", animation);
|
collection.Insert(L"Opacity", m_animation);
|
||||||
m_root.ImplicitAnimations(collection);
|
m_root.ImplicitAnimations(collection);
|
||||||
|
|
||||||
// Radius of spotlight shrinks as opacity increases.
|
// Radius of spotlight shrinks as opacity increases.
|
||||||
// At opacity zero, it is SonarRadius * SonarZoomFactor.
|
// At opacity zero, it is m_sonarRadius * SonarZoomFactor.
|
||||||
// At maximum opacity, it is SonarRadius.
|
// At maximum opacity, it is m_sonarRadius.
|
||||||
auto radiusExpression = m_compositor.CreateExpressionAnimation();
|
auto radiusExpression = m_compositor.CreateExpressionAnimation();
|
||||||
radiusExpression.SetReferenceParameter(L"Root", m_root);
|
radiusExpression.SetReferenceParameter(L"Root", m_root);
|
||||||
wchar_t expressionText[256];
|
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);
|
radiusExpression.Expression(expressionText);
|
||||||
m_circleGeometry.StartAnimation(L"Radius", radiusExpression);
|
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:
|
private:
|
||||||
winrt::Compositor m_compositor{ nullptr };
|
winrt::Compositor m_compositor{ nullptr };
|
||||||
winrt::Desktop::DesktopWindowTarget m_target{ nullptr };
|
winrt::Desktop::DesktopWindowTarget m_target{ nullptr };
|
||||||
|
@ -588,6 +645,11 @@ private:
|
||||||
winrt::CompositionEllipseGeometry m_circleGeometry{ nullptr };
|
winrt::CompositionEllipseGeometry m_circleGeometry{ nullptr };
|
||||||
winrt::ShapeVisual m_spotlight{ nullptr };
|
winrt::ShapeVisual m_spotlight{ nullptr };
|
||||||
winrt::CompositionCommitBatch m_batch{ 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>
|
template<typename D>
|
||||||
|
@ -631,7 +693,7 @@ struct GdiSonar : SuperSonar<D>
|
||||||
void OnFadeTimer()
|
void OnFadeTimer()
|
||||||
{
|
{
|
||||||
auto now = GetTickCount();
|
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();
|
this->Shim()->InvalidateSonar();
|
||||||
if (m_alpha < m_alphaTarget)
|
if (m_alpha < m_alphaTarget)
|
||||||
|
@ -666,13 +728,13 @@ protected:
|
||||||
int CurrentSonarRadius()
|
int CurrentSonarRadius()
|
||||||
{
|
{
|
||||||
int range = MaxAlpha - m_alpha;
|
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;
|
return radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr DWORD FadeFramePeriod = 10;
|
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;
|
static constexpr DWORD TIMER_ID_FADE = 101;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -792,6 +854,14 @@ struct GdiCrosshairs : GdiSonar<GdiCrosshairs>
|
||||||
#pragma region Super_Sonar_API
|
#pragma region Super_Sonar_API
|
||||||
|
|
||||||
CompositionSpotlight* m_sonar = nullptr;
|
CompositionSpotlight* m_sonar = nullptr;
|
||||||
|
void FindMyMouseApplySettings(const FindMyMouseSettings& settings)
|
||||||
|
{
|
||||||
|
if (m_sonar != nullptr)
|
||||||
|
{
|
||||||
|
Logger::info("Applying settings.");
|
||||||
|
m_sonar->ApplySettings(settings, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FindMyMouseDisable()
|
void FindMyMouseDisable()
|
||||||
{
|
{
|
||||||
|
@ -807,13 +877,8 @@ bool FindMyMouseIsEnabled()
|
||||||
return (m_sonar != nullptr);
|
return (m_sonar != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate)
|
|
||||||
{
|
|
||||||
m_doNotActivateOnGameMode = doNotActivate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on SuperSonar's original wWinMain.
|
// Based on SuperSonar's original wWinMain.
|
||||||
int FindMyMouseMain(HINSTANCE hinst)
|
int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings)
|
||||||
{
|
{
|
||||||
Logger::info("Starting a sonar instance.");
|
Logger::info("Starting a sonar instance.");
|
||||||
if (m_sonar != nullptr)
|
if (m_sonar != nullptr)
|
||||||
|
@ -823,6 +888,7 @@ int FindMyMouseMain(HINSTANCE hinst)
|
||||||
}
|
}
|
||||||
|
|
||||||
CompositionSpotlight sonar;
|
CompositionSpotlight sonar;
|
||||||
|
sonar.ApplySettings(settings, false);
|
||||||
if (!sonar.Initialize(hinst))
|
if (!sonar.Initialize(hinst))
|
||||||
{
|
{
|
||||||
Logger::error("Couldn't initialize a sonar instance.");
|
Logger::error("Couldn't initialize a sonar instance.");
|
||||||
|
|
|
@ -1,6 +1,26 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "pch.h"
|
#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();
|
void FindMyMouseDisable();
|
||||||
bool FindMyMouseIsEnabled();
|
bool FindMyMouseIsEnabled();
|
||||||
void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate);
|
void FindMyMouseApplySettings(const FindMyMouseSettings& settings);
|
||||||
|
|
|
@ -5,13 +5,19 @@
|
||||||
#include "FindMyMouse.h"
|
#include "FindMyMouse.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <common/utils/logger_helper.h>
|
#include <common/utils/logger_helper.h>
|
||||||
|
#include <common/utils/color.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
|
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
|
||||||
const wchar_t JSON_KEY_VALUE[] = L"value";
|
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_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;
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
@ -48,6 +54,9 @@ private:
|
||||||
// The PowerToy state.
|
// The PowerToy state.
|
||||||
bool m_enabled = false;
|
bool m_enabled = false;
|
||||||
|
|
||||||
|
// Find My Mouse specific settings
|
||||||
|
FindMyMouseSettings m_findMyMouseSettings;
|
||||||
|
|
||||||
// Load initial settings from the persisted values.
|
// Load initial settings from the persisted values.
|
||||||
void init_settings();
|
void init_settings();
|
||||||
|
|
||||||
|
@ -109,7 +118,7 @@ public:
|
||||||
|
|
||||||
parse_settings(values);
|
parse_settings(values);
|
||||||
|
|
||||||
values.save_to_settings_file();
|
FindMyMouseApplySettings(m_findMyMouseSettings);
|
||||||
}
|
}
|
||||||
catch (std::exception&)
|
catch (std::exception&)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +131,7 @@ public:
|
||||||
{
|
{
|
||||||
m_enabled = true;
|
m_enabled = true;
|
||||||
Trace::EnableFindMyMouse(true);
|
Trace::EnableFindMyMouse(true);
|
||||||
std::thread([]() { FindMyMouseMain(m_hModule); }).detach();
|
std::thread([=]() { FindMyMouseMain(m_hModule, m_findMyMouseSettings); }).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable the powertoy
|
// Disable the powertoy
|
||||||
|
@ -158,25 +167,103 @@ void FindMyMouse::init_settings()
|
||||||
|
|
||||||
void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
|
void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
|
||||||
{
|
{
|
||||||
FindMyMouseSetDoNotActivateOnGameMode(true);
|
|
||||||
|
|
||||||
auto settingsObject = settings.get_raw_json();
|
auto settingsObject = settings.get_raw_json();
|
||||||
|
FindMyMouseSettings findMyMouseSettings;
|
||||||
if (settingsObject.GetView().Size())
|
if (settingsObject.GetView().Size())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE);
|
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 (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Logger::warn("Failed to get 'do not activate on game mode' setting");
|
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
|
else
|
||||||
{
|
{
|
||||||
Logger::info("Find My Mouse settings are empty");
|
Logger::info("Find My Mouse settings are empty");
|
||||||
}
|
}
|
||||||
|
m_findMyMouseSettings = findMyMouseSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <common/SettingsAPI/settings_objects.h>
|
#include <common/SettingsAPI/settings_objects.h>
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "MouseHighlighter.h"
|
#include "MouseHighlighter.h"
|
||||||
|
#include "common/utils/color.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -57,26 +58,6 @@ private:
|
||||||
// Mouse Highlighter specific settings
|
// Mouse Highlighter specific settings
|
||||||
MouseHighlighterSettings m_highlightSettings;
|
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:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
MouseHighlighter()
|
MouseHighlighter()
|
||||||
|
|
|
@ -11,9 +11,33 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
[JsonPropertyName("do_not_activate_on_game_mode")]
|
[JsonPropertyName("do_not_activate_on_game_mode")]
|
||||||
public BoolProperty DoNotActivateOnGameMode { get; set; }
|
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()
|
public FindMyMouseProperties()
|
||||||
{
|
{
|
||||||
DoNotActivateOnGameMode = new BoolProperty(true);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,17 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
FindMyMouseSettingsConfig = findMyMouseSettingsRepository.SettingsConfig;
|
FindMyMouseSettingsConfig = findMyMouseSettingsRepository.SettingsConfig;
|
||||||
_findMyMouseDoNotActivateOnGameMode = FindMyMouseSettingsConfig.Properties.DoNotActivateOnGameMode.Value;
|
_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)
|
if (mouseHighlighterSettingsRepository == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(mouseHighlighterSettingsRepository));
|
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)
|
public void NotifyFindMyMousePropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
{
|
{
|
||||||
OnPropertyChanged(propertyName);
|
OnPropertyChanged(propertyName);
|
||||||
|
@ -281,6 +402,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
|
|
||||||
private bool _isFindMyMouseEnabled;
|
private bool _isFindMyMouseEnabled;
|
||||||
private bool _findMyMouseDoNotActivateOnGameMode;
|
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 bool _isMouseHighlighterEnabled;
|
||||||
private string _highlighterLeftButtonClickColor;
|
private string _highlighterLeftButtonClickColor;
|
||||||
|
|
|
@ -1733,6 +1733,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>
|
<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>
|
<comment>"Game mode" is the Windows feature to prevent notification when playing a game.</comment>
|
||||||
</data>
|
</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">
|
<data name="MouseUtils_MouseHighlighter.Header" xml:space="preserve">
|
||||||
<value>Mouse Highlighter</value>
|
<value>Mouse Highlighter</value>
|
||||||
<comment>Refers to the utility name</comment>
|
<comment>Refers to the utility name</comment>
|
||||||
|
@ -1745,7 +1769,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>
|
<value>Mouse Highlighter mode will highlight mouse clicks.</value>
|
||||||
<comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment>
|
<comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<data name="MouseUtils_MouseHighlighter_ActivationShortcut.Header" xml:space="preserve">
|
<data name="MouseUtils_MouseHighlighter_ActivationShortcut.Header" xml:space="preserve">
|
||||||
<value>Activation shortcut</value>
|
<value>Activation shortcut</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -1753,7 +1776,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>
|
<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>
|
<comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<data name="MouseUtils_MouseHighlighter_LeftButtonClickColor.Header" xml:space="preserve">
|
<data name="MouseUtils_MouseHighlighter_LeftButtonClickColor.Header" xml:space="preserve">
|
||||||
<value>Left button highlight color</value>
|
<value>Left button highlight color</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<controls:SettingsGroup x:Uid="MouseUtils_FindMyMouse">
|
<controls:SettingsGroup x:Uid="MouseUtils_FindMyMouse">
|
||||||
<TextBlock x:Uid="MouseUtils_FindMyMouse_Description" Margin="0,0,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
<TextBlock x:Uid="MouseUtils_FindMyMouse_Description" Margin="0,0,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||||
<controls:SettingExpander IsExpanded="True">
|
|
||||||
<controls:SettingExpander.Header>
|
|
||||||
<controls:Setting x:Uid="MouseUtils_Enable_FindMyMouse">
|
<controls:Setting x:Uid="MouseUtils_Enable_FindMyMouse">
|
||||||
<controls:Setting.Icon>
|
<controls:Setting.Icon>
|
||||||
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFindMyMouse.png" ShowAsMonochrome="False" />
|
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFindMyMouse.png" ShowAsMonochrome="False" />
|
||||||
|
@ -25,15 +23,71 @@
|
||||||
<ToggleSwitch IsOn="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
|
<ToggleSwitch IsOn="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
|
||||||
</controls:Setting.ActionContent>
|
</controls:Setting.ActionContent>
|
||||||
</controls:Setting>
|
</controls:Setting>
|
||||||
|
<controls:SettingExpander IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}" IsExpanded="False" >
|
||||||
|
<controls:SettingExpander.Header>
|
||||||
|
<controls:Setting x:Uid="ShortcutGuide_Appearance_Behavior" Icon="" />
|
||||||
</controls:SettingExpander.Header>
|
</controls:SettingExpander.Header>
|
||||||
<controls:SettingExpander.Content>
|
<controls:SettingExpander.Content>
|
||||||
|
<StackPanel>
|
||||||
<CheckBox x:Uid="MouseUtils_Prevent_Activation_On_Game_Mode"
|
<CheckBox x:Uid="MouseUtils_Prevent_Activation_On_Game_Mode"
|
||||||
IsChecked="{x:Bind ViewModel.FindMyMouseDoNotActivateOnGameMode, Mode=TwoWay}"
|
IsChecked="{x:Bind ViewModel.FindMyMouseDoNotActivateOnGameMode, Mode=TwoWay}"
|
||||||
Margin="{StaticResource ExpanderSettingMargin}"
|
Margin="{StaticResource ExpanderSettingMargin}"
|
||||||
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}" />
|
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.Content>
|
||||||
</controls:SettingExpander>
|
</controls:SettingExpander>
|
||||||
</controls:SettingsGroup>
|
</controls:SettingsGroup>
|
||||||
|
|
||||||
<controls:SettingsGroup x:Uid="MouseUtils_MouseHighlighter">
|
<controls:SettingsGroup x:Uid="MouseUtils_MouseHighlighter">
|
||||||
<TextBlock x:Uid="MouseUtils_MouseHighlighter_Description" Margin="0,0,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
<TextBlock x:Uid="MouseUtils_MouseHighlighter_Description" Margin="0,0,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||||
<controls:Setting x:Uid="MouseUtils_Enable_MouseHighlighter">
|
<controls:Setting x:Uid="MouseUtils_Enable_MouseHighlighter">
|
||||||
|
@ -53,7 +107,7 @@
|
||||||
</controls:Setting.ActionContent>
|
</controls:Setting.ActionContent>
|
||||||
</controls:Setting>
|
</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:SettingExpander.Header>
|
||||||
<controls:Setting x:Uid="ShortcutGuide_Appearance_Behavior" Icon="" />
|
<controls:Setting x:Uid="ShortcutGuide_Appearance_Behavior" Icon="" />
|
||||||
</controls:SettingExpander.Header>
|
</controls:SettingExpander.Header>
|
||||||
|
|
Loading…
Reference in a new issue