diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index f202cf06c6..b273d11b1d 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -918,6 +918,7 @@ LWA
lwin
LZero
MAGTRANSFORM
+MAJORMINOR
MAKEINTRESOURCE
MAKEINTRESOURCEA
MAKEINTRESOURCEW
@@ -996,6 +997,9 @@ mousepointercrosshairs
mouseutils
MOVESIZEEND
MOVESIZESTART
+muxx
+muxxc
+muxxh
MRM
MRT
mru
@@ -1807,6 +1811,7 @@ ULONGLONG
ums
uncompilable
UNCPRIORITY
+undefining
UNDNAME
UNICODETEXT
unins
diff --git a/Directory.Build.props b/Directory.Build.props
index 4184a8f2a3..e7b415cbca 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -30,7 +30,6 @@
<_PropertySheetDisplayName>PowerToys.Root.Props
$(MsbuildThisFileDirectory)\Cpp.Build.props
-
all
diff --git a/Directory.Build.targets b/Directory.Build.targets
index cba7762d5f..6da66bc8a8 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -3,4 +3,9 @@
+
+
+
+ $(WindowsSdkDir)bin\x64\mt.exe
+
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 23dac30258..e355bf6d7c 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -37,6 +37,7 @@
+
diff --git a/nuget.config b/nuget.config
index 51f9b3b3f7..6b8d13a023 100644
--- a/nuget.config
+++ b/nuget.config
@@ -9,4 +9,4 @@
-
+
\ No newline at end of file
diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp
index 3049d3740c..adf5075837 100644
--- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp
+++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp
@@ -8,21 +8,28 @@
#include "common/utils/process_path.h"
#include "common/utils/excluded_apps.h"
#include "common/utils/MsWindowsSettings.h"
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
#include
-#ifdef COMPOSITION
namespace winrt
{
using namespace winrt::Windows::System;
- using namespace winrt::Windows::UI::Composition;
}
-namespace ABI
-{
- using namespace ABI::Windows::System;
- using namespace ABI::Windows::UI::Composition::Desktop;
-}
-#endif
+namespace muxc = winrt::Microsoft::UI::Composition;
+namespace muxx = winrt::Microsoft::UI::Xaml;
+namespace muxxc = winrt::Microsoft::UI::Xaml::Controls;
+namespace muxxh = winrt::Microsoft::UI::Xaml::Hosting;
#pragma region Super_Sonar_Base_Code
@@ -70,11 +77,11 @@ protected:
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;
+ int m_finalAlphaNumerator = 100; // legacy (root now always animates to 1.0; kept for GDI fallback compatibility)
std::vector m_excludedApps;
int m_shakeMinimumDistance = FIND_MY_MOUSE_DEFAULT_SHAKE_MINIMUM_DISTANCE;
static constexpr int FinalAlphaDenominator = 100;
- winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
+ winrt::Microsoft::UI::Dispatching::DispatcherQueueController m_dispatcherQueueController{ nullptr };
// Don't consider movements started past these milliseconds to detect shaking.
int m_shakeIntervalMs = FIND_MY_MOUSE_DEFAULT_SHAKE_INTERVAL_MS;
@@ -82,7 +89,6 @@ protected:
int m_shakeFactor = FIND_MY_MOUSE_DEFAULT_SHAKE_FACTOR;
private:
-
// Save the mouse movement that occurred in any direction.
struct PointerRecentMovement
{
@@ -159,7 +165,6 @@ bool SuperSonar::Initialize(HINSTANCE hinst)
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
WNDCLASS wc{};
-
if (!GetClassInfoW(hinst, className, &wc))
{
wc.lpfnWndProc = s_WndProc;
@@ -171,14 +176,28 @@ bool SuperSonar::Initialize(HINSTANCE hinst)
if (!RegisterClassW(&wc))
{
+ Logger::error("RegisterClassW failed. GetLastError={}", GetLastError());
return false;
}
}
+ // else: class already registered
m_hwndOwner = CreateWindow(L"static", nullptr, WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, hinst, nullptr);
+ if (!m_hwndOwner)
+ {
+ Logger::error("Failed to create owner window. GetLastError={}", GetLastError());
+ return false;
+ }
- DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOOLWINDOW | Shim()->GetExtendedStyle();
- return CreateWindowExW(exStyle, className, windowTitle, WS_POPUP, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, m_hwndOwner, nullptr, hinst, this) != nullptr;
+ DWORD exStyle = WS_EX_TOOLWINDOW | Shim()->GetExtendedStyle();
+ HWND created = CreateWindowExW(exStyle, className, windowTitle, WS_POPUP, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, m_hwndOwner, nullptr, hinst, this);
+ if (!created)
+ {
+ Logger::error("CreateWindowExW failed. GetLastError={}", GetLastError());
+ return false;
+ }
+
+ return true;
}
template
@@ -226,7 +245,8 @@ LRESULT SuperSonar::BaseWndProc(UINT message, WPARAM wParam, LPARAM lParam) n
switch (message)
{
case WM_CREATE:
- if(!OnSonarCreate()) return -1;
+ if (!OnSonarCreate())
+ return -1;
UpdateMouseSnooping();
return 0;
@@ -314,8 +334,7 @@ void SuperSonar::OnSonarKeyboardInput(RAWINPUT const& input)
return;
}
- if ((m_activationMethod != FindMyMouseActivationMethod::DoubleRightControlKey && m_activationMethod != FindMyMouseActivationMethod::DoubleLeftControlKey)
- || input.data.keyboard.VKey != VK_CONTROL)
+ if ((m_activationMethod != FindMyMouseActivationMethod::DoubleRightControlKey && m_activationMethod != FindMyMouseActivationMethod::DoubleLeftControlKey) || input.data.keyboard.VKey != VK_CONTROL)
{
StopSonar();
return;
@@ -326,8 +345,7 @@ void SuperSonar::OnSonarKeyboardInput(RAWINPUT const& input)
bool leftCtrlPressed = (input.data.keyboard.Flags & RI_KEY_E0) == 0;
bool rightCtrlPressed = (input.data.keyboard.Flags & RI_KEY_E0) != 0;
- if ((m_activationMethod == FindMyMouseActivationMethod::DoubleRightControlKey && !rightCtrlPressed)
- || (m_activationMethod == FindMyMouseActivationMethod::DoubleLeftControlKey && !leftCtrlPressed))
+ if ((m_activationMethod == FindMyMouseActivationMethod::DoubleRightControlKey && !rightCtrlPressed) || (m_activationMethod == FindMyMouseActivationMethod::DoubleLeftControlKey && !leftCtrlPressed))
{
StopSonar();
return;
@@ -376,7 +394,6 @@ void SuperSonar::OnSonarKeyboardInput(RAWINPUT const& input)
GetCursorPos(&m_lastKeyPos);
UpdateMouseSnooping();
}
- Logger::info("Detecting double left control click with {} ms interval.", doubleClickInterval);
m_lastKeyTime = now;
m_lastKeyPos = ptCursor;
}
@@ -402,14 +419,13 @@ template
void SuperSonar::DetectShake()
{
ULONGLONG shakeStartTick = GetTickCount64() - m_shakeIntervalMs;
-
+
// Prune the story of movements for those movements that started too long ago.
std::erase_if(m_movementHistory, [shakeStartTick](const PointerRecentMovement& movement) { return movement.tick < shakeStartTick; });
-
-
+
double distanceTravelled = 0;
- LONGLONG currentX=0, minX=0, maxX=0;
- LONGLONG currentY=0, minY=0, maxY=0;
+ LONGLONG currentX = 0, minX = 0, maxX = 0;
+ LONGLONG currentY = 0, minY = 0, maxY = 0;
for (const PointerRecentMovement& movement : m_movementHistory)
{
@@ -421,23 +437,22 @@ void SuperSonar::DetectShake()
minY = min(currentY, minY);
maxY = max(currentY, maxY);
}
-
+
if (distanceTravelled < m_shakeMinimumDistance)
{
return;
}
// Size of the rectangle that the pointer moved in.
- double rectangleWidth = static_cast(maxX) - minX;
- double rectangleHeight = static_cast(maxY) - minY;
+ double rectangleWidth = static_cast(maxX) - minX;
+ double rectangleHeight = static_cast(maxY) - minY;
double diagonal = sqrt(rectangleWidth * rectangleWidth + rectangleHeight * rectangleHeight);
- if (diagonal > 0 && distanceTravelled / diagonal > (m_shakeFactor/100.f))
+ if (diagonal > 0 && distanceTravelled / diagonal > (m_shakeFactor / 100.f))
{
m_movementHistory.clear();
StartSonar();
}
-
}
template
@@ -453,7 +468,7 @@ void SuperSonar::OnSonarMouseInput(RAWINPUT const& input)
{
LONG relativeX = 0;
LONG relativeY = 0;
- if ((input.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) == MOUSE_MOVE_ABSOLUTE && (input.data.mouse.lLastX!=0 || input.data.mouse.lLastY!=0))
+ if ((input.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) == MOUSE_MOVE_ABSOLUTE && (input.data.mouse.lLastX != 0 || input.data.mouse.lLastY != 0))
{
// Getting absolute mouse coordinates. Likely inside a VM / RDP session.
if (m_seenAnAbsoluteMousePosition)
@@ -482,7 +497,7 @@ void SuperSonar::OnSonarMouseInput(RAWINPUT const& input)
}
else
{
- m_movementHistory.push_back({ .diff = { .x=relativeX, .y=relativeY }, .tick = GetTickCount64() });
+ m_movementHistory.push_back({ .diff = { .x = relativeX, .y = relativeY }, .tick = GetTickCount64() });
// Mouse movement changed directions. Take the opportunity do detect shake.
DetectShake();
}
@@ -491,7 +506,6 @@ void SuperSonar::OnSonarMouseInput(RAWINPUT const& input)
{
m_movementHistory.push_back({ .diff = { .x = relativeX, .y = relativeY }, .tick = GetTickCount64() });
}
-
}
if (input.data.mouse.usButtonFlags)
@@ -518,7 +532,6 @@ void SuperSonar::StartSonar()
return;
}
- Logger::info("Focusing the sonar on the mouse cursor.");
Trace::MousePointerFocused();
// Cover the entire virtual screen.
// HACK: Draw with 1 pixel off. Otherwise, Windows glitches the task bar transparency when a transparent window fill the whole screen.
@@ -633,12 +646,26 @@ struct CompositionSpotlight : SuperSonar
DWORD GetExtendedStyle()
{
- return WS_EX_NOREDIRECTIONBITMAP;
+ // Remove WS_EX_NOREDIRECTIONBITMAP for Composition/XAML to allow DWM redirection.
+ return 0;
}
void AfterMoveSonar()
{
- m_spotlight.Offset({ static_cast(m_sonarPos.x), static_cast(m_sonarPos.y), 0.0f });
+ const float scale = static_cast(m_surface.XamlRoot().RasterizationScale());
+ // Move gradient center
+ if (m_spotlightMaskGradient)
+ {
+ m_spotlightMaskGradient.EllipseCenter({ static_cast(m_sonarPos.x) / scale,
+ static_cast(m_sonarPos.y) / scale });
+ }
+ // Move spotlight visual (color fill) below masked backdrop
+ if (m_spotlight)
+ {
+ m_spotlight.Offset({ static_cast(m_sonarPos.x) / scale,
+ static_cast(m_sonarPos.y) / scale,
+ 0.0f });
+ }
}
LRESULT WndProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept
@@ -646,24 +673,29 @@ struct CompositionSpotlight : SuperSonar
switch (message)
{
case WM_CREATE:
- return OnCompositionCreate() && BaseWndProc(message, wParam, lParam);
+ if (!OnCompositionCreate())
+ return -1;
+ return BaseWndProc(message, wParam, lParam);
case WM_OPACITY_ANIMATION_COMPLETED:
OnOpacityAnimationCompleted();
break;
+ case WM_SIZE:
+ UpdateIslandSize();
+ break;
}
return BaseWndProc(message, wParam, lParam);
}
void SetSonarVisibility(bool visible)
{
- m_batch = m_compositor.GetCommitBatch(winrt::CompositionBatchTypes::Animation);
+ m_batch = m_compositor.GetCommitBatch(muxc::CompositionBatchTypes::Animation);
BOOL isEnabledAnimations = GetAnimationsEnabled();
m_animation.Duration(std::chrono::milliseconds{ isEnabledAnimations ? m_fadeDuration : 1 });
m_batch.Completed([hwnd = m_hwnd](auto&&, auto&&) {
PostMessage(hwnd, WM_OPACITY_ANIMATION_COMPLETED, 0, 0);
});
- m_root.Opacity(visible ? static_cast(m_finalAlphaNumerator) / FinalAlphaDenominator : 0.0f);
+ m_root.Opacity(visible ? 1.0f : 0.0f);
if (visible)
{
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
@@ -679,54 +711,138 @@ private:
bool OnCompositionCreate()
try
{
- // We need a dispatcher queue.
- DispatcherQueueOptions options = {
- sizeof(options),
- DQTYPE_THREAD_CURRENT,
- DQTAT_COM_ASTA,
- };
- ABI::IDispatcherQueueController* controller;
- winrt::check_hresult(CreateDispatcherQueueController(options, &controller));
- *winrt::put_abi(m_dispatcherQueueController) = controller;
+ // Creating composition resources
+ // Ensure a DispatcherQueue bound to this thread (required by WinAppSDK composition/XAML)
+ if (!m_dispatcherQueueController)
+ {
+ // Ensure COM is initialized
+ try
+ {
+ winrt::init_apartment(winrt::apartment_type::single_threaded);
+ // COM STA initialized
+ }
+ catch (const winrt::hresult_error& e)
+ {
+ Logger::error("Failed to initialize COM apartment: {}", winrt::to_string(e.message()));
+ return false;
+ }
- // Create the compositor for our window.
- m_compositor = winrt::Compositor();
- ABI::IDesktopWindowTarget* target;
- winrt::check_hresult(m_compositor.as()->CreateDesktopWindowTarget(m_hwnd, false, &target));
- *winrt::put_abi(m_target) = target;
+ try
+ {
+ m_dispatcherQueueController =
+ winrt::Microsoft::UI::Dispatching::DispatcherQueueController::CreateOnCurrentThread();
+ // DispatcherQueueController created
+ }
+ catch (const winrt::hresult_error& e)
+ {
+ Logger::error("Failed to create DispatcherQueueController: {}", winrt::to_string(e.message()));
+ return false;
+ }
+ }
- // Our composition tree:
+ // 1) Create a XAML island and attach it to this HWND
+ try
+ {
+ m_island = winrt::Microsoft::UI::Xaml::Hosting::DesktopWindowXamlSource{};
+ auto windowId = winrt::Microsoft::UI::GetWindowIdFromWindow(m_hwnd);
+ m_island.Initialize(windowId);
+ // Xaml source initialized
+ }
+ catch (const winrt::hresult_error& e)
+ {
+ Logger::error("Failed to create XAML island: {}", winrt::to_string(e.message()));
+ return false;
+ }
+
+ UpdateIslandSize();
+ // Island size set
+
+ // 2) Create a XAML container to host the Composition child visual
+ m_surface = winrt::Microsoft::UI::Xaml::Controls::Grid{};
+
+ // A transparent background keeps hit-testing consistent vs. null brush
+ m_surface.Background(winrt::Microsoft::UI::Xaml::Media::SolidColorBrush{
+ winrt::Microsoft::UI::Colors::Transparent() });
+ m_surface.HorizontalAlignment(muxx::HorizontalAlignment::Stretch);
+ m_surface.VerticalAlignment(muxx::VerticalAlignment::Stretch);
+
+ m_island.Content(m_surface);
+
+ // 3) Get the compositor from the XAML visual tree (pure MUXC path)
+ try
+ {
+ auto elementVisual =
+ winrt::Microsoft::UI::Xaml::Hosting::ElementCompositionPreview::GetElementVisual(m_surface);
+ m_compositor = elementVisual.Compositor();
+ // Compositor acquired
+ }
+ catch (const winrt::hresult_error& e)
+ {
+ Logger::error("Failed to get compositor: {}", winrt::to_string(e.message()));
+ return false;
+ }
+
+ // 4) Build the composition tree
//
- // [root] ContainerVisual
- // \ LayerVisual
- // \[gray backdrop]
- // [spotlight]
+ // [root] ContainerVisual (fills host)
+ // \ LayerVisual
+ // \ [backdrop dim * radial gradient mask (hole)]
m_root = m_compositor.CreateContainerVisual();
- m_root.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
+ m_root.RelativeSizeAdjustment({ 1.0f, 1.0f });
m_root.Opacity(0.0f);
- m_target.Root(m_root);
+
+ // Insert our root as a hand-in Visual under the XAML element
+ winrt::Microsoft::UI::Xaml::Hosting::ElementCompositionPreview::SetElementChildVisual(m_surface, m_root);
auto layer = m_compositor.CreateLayerVisual();
- layer.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
+ layer.RelativeSizeAdjustment({ 1.0f, 1.0f });
m_root.Children().InsertAtTop(layer);
- 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);
+ const float scale = static_cast(m_surface.XamlRoot().RasterizationScale());
+ const float rDip = m_sonarRadiusFloat / scale;
+ const float zoom = static_cast(m_sonarZoomFactor);
- m_circleGeometry = m_compositor.CreateEllipseGeometry(); // radius set via expression animation
+ // Spotlight shape (below backdrop, visible through hole)
+ m_circleGeometry = m_compositor.CreateEllipseGeometry();
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_circleShape.Offset({ rDip * zoom, rDip * zoom });
m_spotlight = m_compositor.CreateShapeVisual();
- m_spotlight.Size({ m_sonarRadiusFloat * 2 * m_sonarZoomFactor, m_sonarRadiusFloat * 2 * m_sonarZoomFactor });
+ m_spotlight.Size({ rDip * 2 * zoom, rDip * 2 * zoom });
m_spotlight.AnchorPoint({ 0.5f, 0.5f });
m_spotlight.Shapes().Append(m_circleShape);
-
layer.Children().InsertAtTop(m_spotlight);
- // Implicitly animate the alpha.
+ // Dim color (source)
+ m_dimColorBrush = m_compositor.CreateColorBrush(m_backgroundColor);
+ // Radial gradient mask (center transparent, outer opaque)
+ m_spotlightMaskGradient = m_compositor.CreateRadialGradientBrush();
+ m_spotlightMaskGradient.MappingMode(muxc::CompositionMappingMode::Absolute);
+ m_maskStopCenter = m_compositor.CreateColorGradientStop();
+ m_maskStopCenter.Offset(0.0f);
+ m_maskStopCenter.Color(winrt::Windows::UI::ColorHelper::FromArgb(0, 0, 0, 0));
+ m_maskStopInner = m_compositor.CreateColorGradientStop();
+ m_maskStopInner.Offset(0.995f);
+ m_maskStopInner.Color(winrt::Windows::UI::ColorHelper::FromArgb(0, 0, 0, 0));
+ m_maskStopOuter = m_compositor.CreateColorGradientStop();
+ m_maskStopOuter.Offset(1.0f);
+ m_maskStopOuter.Color(winrt::Windows::UI::ColorHelper::FromArgb(255, 255, 255, 255));
+ m_spotlightMaskGradient.ColorStops().Append(m_maskStopCenter);
+ m_spotlightMaskGradient.ColorStops().Append(m_maskStopInner);
+ m_spotlightMaskGradient.ColorStops().Append(m_maskStopOuter);
+ m_spotlightMaskGradient.EllipseCenter({ rDip * zoom, rDip * zoom });
+ m_spotlightMaskGradient.EllipseRadius({ rDip * zoom, rDip * zoom });
+
+ m_maskBrush = m_compositor.CreateMaskBrush();
+ m_maskBrush.Source(m_dimColorBrush);
+ m_maskBrush.Mask(m_spotlightMaskGradient);
+
+ m_backdrop = m_compositor.CreateSpriteVisual();
+ m_backdrop.RelativeSizeAdjustment({ 1.0f, 1.0f });
+ m_backdrop.Brush(m_maskBrush);
+ layer.Children().InsertAtTop(m_backdrop);
+
+ // 5) Implicit opacity animation on the root
m_animation = m_compositor.CreateScalarKeyFrameAnimation();
m_animation.Target(L"Opacity");
m_animation.InsertExpressionKeyFrame(1.0f, L"this.FinalValue");
@@ -735,20 +851,31 @@ private:
collection.Insert(L"Opacity", m_animation);
m_root.ImplicitAnimations(collection);
- // Radius of spotlight shrinks as opacity increases.
- // At opacity zero, it is m_sonarRadius * SonarZoomFactor.
- // At maximum opacity, it is m_sonarRadius.
+ // 6) Spotlight radius shrinks as opacity increases (expression 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);
+ wchar_t expressionText[256];
+ winrt::check_hresult(StringCchPrintfW(
+ expressionText, ARRAYSIZE(expressionText), L"Lerp(Vector2(%d, %d), Vector2(%d, %d), Root.Opacity)", m_sonarRadius * m_sonarZoomFactor, m_sonarRadius * m_sonarZoomFactor, m_sonarRadius, m_sonarRadius));
+
+ radiusExpression.Expression(expressionText);
+ m_spotlightMaskGradient.StartAnimation(L"EllipseRadius", radiusExpression);
+ // Also animate spotlight geometry radius for visual consistency
+ if (m_circleGeometry)
+ {
+ auto radiusExpression2 = m_compositor.CreateExpressionAnimation();
+ radiusExpression2.SetReferenceParameter(L"Root", m_root);
+ radiusExpression2.Expression(expressionText);
+ m_circleGeometry.StartAnimation(L"Radius", radiusExpression2);
+ }
+
+ // Composition created successfully
return true;
}
- catch (...)
+ catch (const winrt::hresult_error& e)
{
+ Logger::error("Failed to create FindMyMouse visual: {}", winrt::to_string(e.message()));
return false;
}
@@ -760,11 +887,27 @@ private:
}
}
+ void UpdateIslandSize()
+ {
+ if (!m_island)
+ return;
+
+ RECT rc{};
+ if (!GetClientRect(m_hwnd, &rc))
+ return;
+
+ const int width = rc.right - rc.left;
+ const int height = rc.bottom - rc.top;
+
+ auto bridge = m_island.SiteBridge();
+ bridge.MoveAndResize(winrt::Windows::Graphics::RectInt32{ 0, 0, width, height });
+ }
+
public:
- void ApplySettings(const FindMyMouseSettings& settings, bool applyToRuntimeObjects) {
+ 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(m_sonarRadius);
m_backgroundColor = settings.backgroundColor;
@@ -773,7 +916,6 @@ public:
m_includeWinKey = settings.includeWinKey;
m_doNotActivateOnGameMode = settings.doNotActivateOnGameMode;
m_fadeDuration = settings.animationDurationMs > 0 ? settings.animationDurationMs : 1;
- m_finalAlphaNumerator = settings.overlayOpacity;
m_sonarZoomFactor = settings.spotlightInitialZoom;
m_excludedApps = settings.excludedApps;
m_shakeMinimumDistance = settings.shakeMinimumDistance;
@@ -782,11 +924,9 @@ public:
}
else
{
- // Runtime objects already created. Should update in the owner thread.
if (m_dispatcherQueueController == nullptr)
{
Logger::warn("Tried accessing the dispatch queue controller before it was initialized.");
- // No dispatcher Queue Controller? Means initialization still hasn't run, so settings will be applied then.
return;
}
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
@@ -794,7 +934,6 @@ public:
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
if (!m_destroyed)
{
- // Runtime objects not created yet. Just update fields.
m_sonarRadius = localSettings.spotlightRadius;
m_sonarRadiusFloat = static_cast(m_sonarRadius);
m_backgroundColor = localSettings.backgroundColor;
@@ -803,7 +942,6 @@ public:
m_includeWinKey = localSettings.includeWinKey;
m_doNotActivateOnGameMode = localSettings.doNotActivateOnGameMode;
m_fadeDuration = localSettings.animationDurationMs > 0 ? localSettings.animationDurationMs : 1;
- m_finalAlphaNumerator = localSettings.overlayOpacity;
m_sonarZoomFactor = localSettings.spotlightInitialZoom;
m_excludedApps = localSettings.excludedApps;
m_shakeMinimumDistance = localSettings.shakeMinimumDistance;
@@ -812,20 +950,41 @@ public:
UpdateMouseSnooping(); // For the shake mouse activation method
// Apply new settings to runtime composition objects.
- m_backdrop.Brush().as().Color(m_backgroundColor);
- m_circleShape.FillBrush().as().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
+ if (m_dimColorBrush)
+ {
+ m_dimColorBrush.Color(m_backgroundColor);
+ }
+ if (m_circleShape)
+ {
+ if (auto brush = m_circleShape.FillBrush().try_as())
+ {
+ brush.Color(m_spotlightColor);
+ }
+ }
+ const float scale = static_cast(m_surface.XamlRoot().RasterizationScale());
+ const float rDip = m_sonarRadiusFloat / scale;
+ const float zoom = static_cast(m_sonarZoomFactor);
+ m_spotlightMaskGradient.StopAnimation(L"EllipseRadius");
+ m_spotlightMaskGradient.EllipseCenter({ rDip * zoom, rDip * zoom });
+ if (m_spotlight)
+ {
+ m_spotlight.Size({ rDip * 2 * zoom, rDip * 2 * zoom });
+ m_circleShape.Offset({ rDip * zoom, rDip * zoom });
+ }
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));
+ winrt::check_hresult(StringCchPrintfW(expressionText, ARRAYSIZE(expressionText), L"Lerp(Vector2(%d, %d), Vector2(%d, %d), Root.Opacity)", m_sonarRadius * m_sonarZoomFactor, m_sonarRadius * m_sonarZoomFactor, m_sonarRadius, m_sonarRadius));
radiusExpression.Expression(expressionText);
- m_circleGeometry.StartAnimation(L"Radius", radiusExpression);
+ m_spotlightMaskGradient.StartAnimation(L"EllipseRadius", radiusExpression);
+ if (m_circleGeometry)
+ {
+ m_circleGeometry.StopAnimation(L"Radius");
+ auto radiusExpression2 = m_compositor.CreateExpressionAnimation();
+ radiusExpression2.SetReferenceParameter(L"Root", m_root);
+ radiusExpression2.Expression(expressionText);
+ m_circleGeometry.StartAnimation(L"Radius", radiusExpression2);
+ }
}
});
if (!enqueueSucceeded)
@@ -836,17 +995,27 @@ public:
}
private:
- winrt::Compositor m_compositor{ nullptr };
- winrt::Desktop::DesktopWindowTarget m_target{ nullptr };
- winrt::ContainerVisual m_root{ nullptr };
- 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 };
+ muxc::Compositor m_compositor{ nullptr };
+ muxxh::DesktopWindowXamlSource m_island{ nullptr };
+ muxxc::Grid m_surface{ nullptr };
+
+ muxc::ContainerVisual m_root{ nullptr };
+ muxc::CompositionCommitBatch m_batch{ nullptr };
+ muxc::SpriteVisual m_backdrop{ nullptr };
+ // Spotlight shape visuals
+ muxc::CompositionEllipseGeometry m_circleGeometry{ nullptr };
+ muxc::ShapeVisual m_spotlight{ nullptr };
+ muxc::CompositionSpriteShape m_circleShape{ nullptr };
+ // Radial gradient mask components
+ muxc::CompositionMaskBrush m_maskBrush{ nullptr };
+ muxc::CompositionColorBrush m_dimColorBrush{ nullptr };
+ muxc::CompositionRadialGradientBrush m_spotlightMaskGradient{ nullptr };
+ muxc::CompositionColorGradientStop m_maskStopCenter{ nullptr };
+ muxc::CompositionColorGradientStop m_maskStopInner{ nullptr };
+ muxc::CompositionColorGradientStop m_maskStopOuter{ 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 };
+ muxc::ScalarKeyFrameAnimation m_animation{ nullptr };
};
template
@@ -1047,7 +1216,6 @@ struct GdiCrosshairs : GdiSonar
#pragma endregion Super_Sonar_Base_Code
-
#pragma region Super_Sonar_API
CompositionSpotlight* m_sonar = nullptr;
@@ -1055,7 +1223,6 @@ void FindMyMouseApplySettings(const FindMyMouseSettings& settings)
{
if (m_sonar != nullptr)
{
- Logger::info("Applying settings.");
m_sonar->ApplySettings(settings, true);
}
}
@@ -1064,7 +1231,6 @@ void FindMyMouseDisable()
{
if (m_sonar != nullptr)
{
- Logger::info("Terminating a sonar instance.");
m_sonar->Terminate();
}
}
@@ -1077,7 +1243,6 @@ bool FindMyMouseIsEnabled()
// Based on SuperSonar's original wWinMain.
int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings)
{
- Logger::info("Starting a sonar instance.");
if (m_sonar != nullptr)
{
Logger::error("A sonar instance was still working when trying to start a new one.");
@@ -1092,7 +1257,6 @@ int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings)
return 0;
}
m_sonar = &sonar;
- Logger::info("Initialized the sonar instance.");
InitializeWinhookEventIds();
@@ -1105,7 +1269,6 @@ int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings)
DispatchMessage(&msg);
}
- Logger::info("Sonar message loop ended.");
m_sonar = nullptr;
return (int)msg.wParam;
diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h
index fb52bf11e5..857ec8b84f 100644
--- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h
+++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h
@@ -11,9 +11,9 @@ enum struct FindMyMouseActivationMethod : int
};
constexpr bool FIND_MY_MOUSE_DEFAULT_DO_NOT_ACTIVATE_ON_GAME_MODE = true;
+// Default colors now include full alpha. Opacity is encoded directly in color alpha (legacy overlay_opacity migrated into A channel)
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;
@@ -30,7 +30,6 @@ 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;
diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj
index 9d4dbd2b28..d127de245e 100644
--- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj
+++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj
@@ -1,5 +1,12 @@
+
+
+
+
+
+
+
15.0
@@ -7,6 +14,14 @@
Win32Proj
FindMyMouse
FindMyMouse
+ true
+ false
+ false
+ false
+ true
+ false
+
+ packages.config
@@ -30,6 +45,7 @@
+
..\..\..\..\$(Platform)\$(Configuration)\
@@ -79,7 +95,8 @@
- $(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)
+
+ $(GeneratedFilesDir);$(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;$(MSBuildThisFileDirectory)..\..\..\..\src\;$(MSBuildThisFileDirectory)..\..\..\..\src\modules;$(MSBuildThisFileDirectory)..\..\..\..\src\common\Telemetry;%(AdditionalIncludeDirectories)
@@ -98,6 +115,7 @@
+
{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}
@@ -112,16 +130,56 @@
+
+
+
+
+
+
+ NotUsing
+
+
+
+
+ <_ToDelete Include="$(OutDir)Microsoft.Web.WebView2.Core.dll" />
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp
index 0518f468c2..b7ffb6177a 100644
--- a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp
+++ b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp
@@ -18,7 +18,7 @@ namespace
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_OVERLAY_OPACITY[] = L"overlay_opacity"; // legacy only (migrated into color alpha)
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";
@@ -204,6 +204,22 @@ void FindMyMouse::init_settings()
}
}
+inline static uint8_t LegacyOpacityToAlpha(int overlayOpacityPercent)
+{
+ if (overlayOpacityPercent < 0)
+ {
+ return 255; // fallback: fully opaque
+ }
+
+ if (overlayOpacityPercent > 100)
+ {
+ overlayOpacityPercent = 100;
+ }
+
+ // Round to nearest integer (0–255)
+ return static_cast((overlayOpacityPercent * 255 + 50) / 100);
+}
+
void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
auto settingsObject = settings.get_raw_json();
@@ -224,14 +240,13 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
}
else
{
- findMyMouseSettings.activationMethod = static_cast(value);
- }
+ findMyMouseSettings.activationMethod = static_cast(value);
+ }
}
else
{
throw std::runtime_error("Invalid Activation Method value");
}
-
}
catch (...)
{
@@ -255,19 +270,49 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
Logger::warn("Failed to get 'do not activate on game mode' setting");
}
+ // Colors + legacy overlay opacity migration
+ // Desired behavior:
+ // - Old schema: colors stored as RGB (no alpha) + separate overlay_opacity (0-100). We should migrate by applying that opacity as alpha.
+ // - New schema: colors stored as ARGB (alpha embedded). Ignore overlay_opacity even if still present.
+ int legacyOverlayOpacity = -1;
+ bool backgroundColorHadExplicitAlpha = false;
+ bool spotlightColorHadExplicitAlpha = false;
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))
+ auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_OVERLAY_OPACITY);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0 && value <= 100)
{
- Logger::error("Background color RGB value is invalid. Will use default value");
+ legacyOverlayOpacity = value;
+ }
+ }
+ catch (...)
+ {
+ // overlay_opacity may not exist anymore
+ }
+ try
+ {
+ auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_BACKGROUND_COLOR);
+ auto backgroundColorStr = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
+ uint8_t a = 255, r, g, b;
+ bool parsed = false;
+ if (checkValidARGB(backgroundColorStr, &a, &r, &g, &b))
+ {
+ parsed = true;
+ backgroundColorHadExplicitAlpha = true; // New schema with alpha present
+ }
+ else if (checkValidRGB(backgroundColorStr, &r, &g, &b))
+ {
+ a = LegacyOpacityToAlpha(legacyOverlayOpacity);
+ parsed = true; // Old schema (no alpha component)
+ }
+ if (parsed)
+ {
+ findMyMouseSettings.backgroundColor = winrt::Windows::UI::ColorHelper::FromArgb(a, r, g, b);
}
else
{
- findMyMouseSettings.backgroundColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
+ Logger::error("Background color value is invalid. Will use default");
}
}
catch (...)
@@ -276,17 +321,27 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
}
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))
+ auto spotlightColorStr = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
+ uint8_t a = 255, r, g, b;
+ bool parsed = false;
+ if (checkValidARGB(spotlightColorStr, &a, &r, &g, &b))
{
- Logger::error("Spotlight color RGB value is invalid. Will use default value");
+ parsed = true;
+ spotlightColorHadExplicitAlpha = true;
+ }
+ else if (checkValidRGB(spotlightColorStr, &r, &g, &b))
+ {
+ a = LegacyOpacityToAlpha(legacyOverlayOpacity);
+ parsed = true;
+ }
+ if (parsed)
+ {
+ findMyMouseSettings.spotlightColor = winrt::Windows::UI::ColorHelper::FromArgb(a, r, g, b);
}
else
{
- findMyMouseSettings.spotlightColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
+ Logger::error("Spotlight color value is invalid. Will use default");
}
}
catch (...)
@@ -294,24 +349,6 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
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);
- int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
- if (value >= 0)
- {
- findMyMouseSettings.overlayOpacity = value;
- }
- else
- {
- throw std::runtime_error("Invalid Overlay Opacity 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);
@@ -492,7 +529,6 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
m_findMyMouseSettings = findMyMouseSettings;
}
-
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
{
return new FindMyMouse();
diff --git a/src/modules/MouseUtils/FindMyMouse/packages.config b/src/modules/MouseUtils/FindMyMouse/packages.config
index 09bfc449e2..cff3aa8705 100644
--- a/src/modules/MouseUtils/FindMyMouse/packages.config
+++ b/src/modules/MouseUtils/FindMyMouse/packages.config
@@ -1,4 +1,12 @@
-
+
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
diff --git a/src/modules/MouseUtils/FindMyMouse/pch.h b/src/modules/MouseUtils/FindMyMouse/pch.h
index 26da2455f2..a0a8f1819c 100644
--- a/src/modules/MouseUtils/FindMyMouse/pch.h
+++ b/src/modules/MouseUtils/FindMyMouse/pch.h
@@ -5,15 +5,22 @@
#include
#include
#include
+// Required for IUnknown and DECLARE_INTERFACE_* used by interop headers
+#include
#ifdef COMPOSITION
-#include
#include
#include
#include
-#include
+#include
+#include
+#include
#endif
#include
#include
#include
+
+#ifdef GetCurrentTime
+#undef GetCurrentTime
+#endif
\ No newline at end of file
diff --git a/src/runner/main.cpp b/src/runner/main.cpp
index 31afbd0378..cc8e6ca2b0 100644
--- a/src/runner/main.cpp
+++ b/src/runner/main.cpp
@@ -335,6 +335,7 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR l
GdiplusStartup(&gpToken, &gpStartupInput, NULL);
winrt::init_apartment();
+
const wchar_t* securityDescriptor =
L"O:BA" // Owner: Builtin (local) administrator
L"G:BA" // Group: Builtin (local) administrator
@@ -526,5 +527,6 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR l
}
}
stop_tray_icon();
+
return result;
}
diff --git a/src/runner/packages.config b/src/runner/packages.config
index ff4b059648..74d5ef5747 100644
--- a/src/runner/packages.config
+++ b/src/runner/packages.config
@@ -2,4 +2,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/runner/runner.vcxproj b/src/runner/runner.vcxproj
index 90dafb5e45..afff599d8e 100644
--- a/src/runner/runner.vcxproj
+++ b/src/runner/runner.vcxproj
@@ -1,8 +1,7 @@

-
-
+
81010002
@@ -15,10 +14,20 @@
+
+
+
+
+
+
+
+
Application
v143
+ None
+ true
@@ -131,15 +140,38 @@
-
-
+
+
+
+
+
+
+
+
+
+
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs b/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs
index a028eb9e43..f1fe32e1ca 100644
--- a/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs
+++ b/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs
@@ -31,9 +31,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("spotlight_color")]
public StringProperty SpotlightColor { get; set; }
- [JsonPropertyName("overlay_opacity")]
- public IntProperty OverlayOpacity { get; set; }
-
[JsonPropertyName("spotlight_radius")]
public IntProperty SpotlightRadius { get; set; }
@@ -61,9 +58,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library
IncludeWinKey = new BoolProperty(false);
ActivationShortcut = DefaultActivationShortcut;
DoNotActivateOnGameMode = new BoolProperty(true);
- BackgroundColor = new StringProperty("#000000");
- SpotlightColor = new StringProperty("#FFFFFF");
- OverlayOpacity = new IntProperty(50);
+ BackgroundColor = new StringProperty("#FF000000"); // ARGB (#AARRGGBB)
+ SpotlightColor = new StringProperty("#FFFFFFFF");
SpotlightRadius = new IntProperty(100);
AnimationDurationMs = new IntProperty(500);
SpotlightInitialZoom = new IntProperty(9);
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/AlphaColorPickerButton.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/AlphaColorPickerButton.xaml
deleted file mode 100644
index c077042d96..0000000000
--- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/AlphaColorPickerButton.xaml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/AlphaColorPickerButton.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/AlphaColorPickerButton.xaml.cs
deleted file mode 100644
index 24a0d0e448..0000000000
--- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/AlphaColorPickerButton.xaml.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) Microsoft Corporation
-// The Microsoft Corporation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Controls;
-using Windows.UI;
-
-namespace Microsoft.PowerToys.Settings.UI.Controls
-{
- public sealed partial class AlphaColorPickerButton : UserControl
- {
- private Color _selectedColor;
-
- public Color SelectedColor
- {
- get
- {
- return _selectedColor;
- }
-
- set
- {
- if (_selectedColor != value)
- {
- _selectedColor = value;
- SetValue(SelectedColorProperty, value);
- }
- }
- }
-
- public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(AlphaColorPickerButton), new PropertyMetadata(null));
-
- public AlphaColorPickerButton()
- {
- this.InitializeComponent();
- IsEnabledChanged -= AlphaColorPickerButton_IsEnabledChanged;
- SetEnabledState();
- IsEnabledChanged += AlphaColorPickerButton_IsEnabledChanged;
- }
-
- private void AlphaColorPickerButton_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
- {
- SetEnabledState();
- }
-
- private void SetEnabledState()
- {
- if (this.IsEnabled)
- {
- ColorPreviewBorder.Opacity = 1;
- }
- else
- {
- ColorPreviewBorder.Opacity = 0.2;
- }
- }
- }
-}
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorPickerButton.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorPickerButton.xaml
index 10a1e01236..4a46b7dc29 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorPickerButton.xaml
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorPickerButton.xaml
@@ -27,9 +27,9 @@
(bool)GetValue(IsAlphaEnabledProperty);
+ set => SetValue(IsAlphaEnabledProperty, value);
+ }
public ColorPickerButton()
{
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml
index 537d5a1071..514e959629 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml
@@ -117,19 +117,12 @@
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}"
IsExpanded="False">
-
-
-
+
-
+
-
+
-
+
-
+
-
+