diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp index 29ab5419ec..51b93c37a6 100644 --- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp +++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp @@ -75,6 +75,11 @@ protected: static constexpr int FinalAlphaDenominator = 100; winrt::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; + // By which factor must travelled distance be than the diagonal of the rectangle containing the movements. (value in percent) + int m_shakeFactor = FIND_MY_MOUSE_DEFAULT_SHAKE_FACTOR; + private: // Save the mouse movement that occurred in any direction. @@ -87,10 +92,6 @@ private: // Raw Input may give relative or absolute values. Need to take each case into account. bool m_seenAnAbsoluteMousePosition = false; POINT m_lastAbsolutePosition = { 0, 0 }; - // Don't consider movements started past these milliseconds to detect shaking. - static constexpr LONG ShakeIntervalMs = 1000; - // By which factor must travelled distance be than the diagonal of the rectangle containing the movements. - static constexpr float ShakeFactor = 4.0f; static inline byte GetSign(LONG const& num) { @@ -398,7 +399,7 @@ void SuperSonar::OnSonarKeyboardInput(RAWINPUT const& input) template void SuperSonar::DetectShake() { - ULONGLONG shakeStartTick = GetTickCount64() - ShakeIntervalMs; + 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; }); @@ -429,7 +430,7 @@ void SuperSonar::DetectShake() double rectangleHeight = static_cast(maxY) - minY; double diagonal = sqrt(rectangleWidth * rectangleWidth + rectangleHeight * rectangleHeight); - if (diagonal > 0 && distanceTravelled / diagonal > ShakeFactor) + if (diagonal > 0 && distanceTravelled / diagonal > (m_shakeFactor/100.f)) { m_movementHistory.clear(); StartSonar(); @@ -767,6 +768,8 @@ public: m_sonarZoomFactor = settings.spotlightInitialZoom; m_excludedApps = settings.excludedApps; m_shakeMinimumDistance = settings.shakeMinimumDistance; + m_shakeIntervalMs = settings.shakeIntervalMs; + m_shakeFactor = settings.shakeFactor; } else { @@ -794,6 +797,8 @@ public: m_sonarZoomFactor = localSettings.spotlightInitialZoom; m_excludedApps = localSettings.excludedApps; m_shakeMinimumDistance = localSettings.shakeMinimumDistance; + m_shakeIntervalMs = localSettings.shakeIntervalMs; + m_shakeFactor = localSettings.shakeFactor; UpdateMouseSnooping(); // For the shake mouse activation method // Apply new settings to runtime composition objects. diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h index 149e52842b..d55b72a34d 100644 --- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h +++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h @@ -19,6 +19,8 @@ constexpr int FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS = 500; constexpr int FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM = 9; constexpr FindMyMouseActivationMethod FIND_MY_MOUSE_DEFAULT_ACTIVATION_METHOD = FindMyMouseActivationMethod::DoubleLeftControlKey; constexpr int FIND_MY_MOUSE_DEFAULT_SHAKE_MINIMUM_DISTANCE = 1000; +constexpr int FIND_MY_MOUSE_DEFAULT_SHAKE_INTERVAL_MS = 1000; +constexpr int FIND_MY_MOUSE_DEFAULT_SHAKE_FACTOR = 400; // 400 percent struct FindMyMouseSettings { @@ -31,6 +33,8 @@ struct FindMyMouseSettings int animationDurationMs = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS; int spotlightInitialZoom = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM; int shakeMinimumDistance = FIND_MY_MOUSE_DEFAULT_SHAKE_MINIMUM_DISTANCE; + int shakeIntervalMs = FIND_MY_MOUSE_DEFAULT_SHAKE_INTERVAL_MS; + int shakeFactor = FIND_MY_MOUSE_DEFAULT_SHAKE_FACTOR; std::vector excludedApps; }; diff --git a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp index 2d1aa55acc..d0102ba507 100644 --- a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp +++ b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp @@ -23,6 +23,8 @@ namespace const wchar_t JSON_KEY_SPOTLIGHT_INITIAL_ZOOM[] = L"spotlight_initial_zoom"; const wchar_t JSON_KEY_EXCLUDED_APPS[] = L"excluded_apps"; const wchar_t JSON_KEY_SHAKING_MINIMUM_DISTANCE[] = L"shaking_minimum_distance"; + const wchar_t JSON_KEY_SHAKING_INTERVAL_MS[] = L"shaking_interval_ms"; + const wchar_t JSON_KEY_SHAKING_FACTOR[] = L"shaking_factor"; const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"activation_shortcut"; } @@ -396,6 +398,42 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings) { Logger::warn("Failed to initialize Shaking Minimum Distance from settings. Will use default value"); } + try + { + // Parse Shaking Interval Milliseconds + auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SHAKING_INTERVAL_MS); + int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE)); + if (value >= 0) + { + findMyMouseSettings.shakeIntervalMs = value; + } + else + { + throw std::runtime_error("Invalid Shaking Interval Milliseconds value"); + } + } + catch (...) + { + Logger::warn("Failed to initialize Shaking Interval Milliseconds from settings. Will use default value"); + } + try + { + // Parse Shaking Factor + auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SHAKING_FACTOR); + int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE)); + if (value >= 0) + { + findMyMouseSettings.shakeFactor = value; + } + else + { + throw std::runtime_error("Invalid Shaking Factor value"); + } + } + catch (...) + { + Logger::warn("Failed to initialize Shaking Factor from settings. Will use default value"); + } try { diff --git a/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs b/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs index ba97a590d7..2256898b45 100644 --- a/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs +++ b/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs @@ -43,6 +43,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("shaking_minimum_distance")] public IntProperty ShakingMinimumDistance { get; set; } + [JsonPropertyName("shaking_interval_ms")] + public IntProperty ShakingIntervalMs { get; set; } + + [JsonPropertyName("shaking_factor")] + public IntProperty ShakingFactor { get; set; } + public FindMyMouseProperties() { ActivationMethod = new IntProperty(0); @@ -56,6 +62,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library SpotlightInitialZoom = new IntProperty(9); ExcludedApps = new StringProperty(); ShakingMinimumDistance = new IntProperty(1000); + ShakingIntervalMs = new IntProperty(1000); + ShakingFactor = new IntProperty(400); } } } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml index 0228c9f2d4..39aa3e6e95 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml @@ -56,6 +56,26 @@ SpinButtonPlacementMode="Compact" Value="{x:Bind ViewModel.FindMyMouseShakingMinimumDistance, Mode=TwoWay}" /> + + + + + + The minimum distance for mouse shaking activation, for adjusting sensitivity + + Shake Interval (ms) + ms = milliseconds + + + The span of time during which we track mouse movement to detect shaking, for adjusting sensitivity + + + Shake factor (percent) + + + Mouse shaking is detected by checking how much the mouse pointer has travelled when compared to the diagonal of the movement area. Reducing this factor increases sensitivity. + Mouse Highlighter Refers to the utility name diff --git a/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs index f7b9934e58..05d8184a46 100644 --- a/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs @@ -58,6 +58,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels _findMyMouseSpotlightInitialZoom = FindMyMouseSettingsConfig.Properties.SpotlightInitialZoom.Value; _findMyMouseExcludedApps = FindMyMouseSettingsConfig.Properties.ExcludedApps.Value; _findMyMouseShakingMinimumDistance = FindMyMouseSettingsConfig.Properties.ShakingMinimumDistance.Value; + _findMyMouseShakingIntervalMs = FindMyMouseSettingsConfig.Properties.ShakingIntervalMs.Value; + _findMyMouseShakingFactor = FindMyMouseSettingsConfig.Properties.ShakingFactor.Value; ArgumentNullException.ThrowIfNull(mouseHighlighterSettingsRepository); @@ -402,6 +404,42 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } } + public int FindMyMouseShakingIntervalMs + { + get + { + return _findMyMouseShakingIntervalMs; + } + + set + { + if (value != _findMyMouseShakingIntervalMs) + { + _findMyMouseShakingIntervalMs = value; + FindMyMouseSettingsConfig.Properties.ShakingIntervalMs.Value = value; + NotifyFindMyMousePropertyChanged(); + } + } + } + + public int FindMyMouseShakingFactor + { + get + { + return _findMyMouseShakingFactor; + } + + set + { + if (value != _findMyMouseShakingFactor) + { + _findMyMouseShakingFactor = value; + FindMyMouseSettingsConfig.Properties.ShakingFactor.Value = value; + NotifyFindMyMousePropertyChanged(); + } + } + } + public void NotifyFindMyMousePropertyChanged([CallerMemberName] string propertyName = null) { OnPropertyChanged(propertyName); @@ -944,6 +982,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private int _findMyMouseSpotlightInitialZoom; private string _findMyMouseExcludedApps; private int _findMyMouseShakingMinimumDistance; + private int _findMyMouseShakingIntervalMs; + private int _findMyMouseShakingFactor; private GpoRuleConfigured _highlighterEnabledGpoRuleConfiguration; private bool _highlighterEnabledStateIsGPOConfigured;