[FindMyMouse] Add setting for excluded apps (#16308)

* refactor find_app_name_in_path

* Add a setting for excluded apps

* Restore game_mode.h
This commit is contained in:
Jaime Bernardo
2022-02-14 18:22:05 +00:00
committed by GitHub
parent 10a5629fe8
commit 05728a6dc2
11 changed files with 131 additions and 31 deletions

View File

@@ -265,6 +265,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643
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
src\common\utils\EventWaiter.h = src\common\utils\EventWaiter.h src\common\utils\EventWaiter.h = src\common\utils\EventWaiter.h
src\common\utils\excluded_apps.h = src\common\utils\excluded_apps.h
src\common\utils\exec.h = src\common\utils\exec.h src\common\utils\exec.h = src\common\utils\exec.h
src\common\utils\game_mode.h = src\common\utils\game_mode.h src\common\utils\game_mode.h = src\common\utils\game_mode.h
src\common\utils\HDropIterator.h = src\common\utils\HDropIterator.h src\common\utils\HDropIterator.h = src\common\utils\HDropIterator.h

View File

@@ -0,0 +1,19 @@
#pragma once
#include <vector>
#include <string>
// Checks if a process path is included in a list of strings.
bool find_app_name_in_path(const std::wstring& where, const std::vector<std::wstring>& what)
{
for (const auto& row : what)
{
const auto pos = where.rfind(row);
const auto last_slash = where.rfind('\\');
//Check that row occurs in where, and its last occurrence contains in itself the first character after the last backslash.
if (pos != std::wstring::npos && pos <= last_slash + 1 && pos + row.length() > last_slash)
{
return true;
}
}
return false;
}

View File

@@ -4,6 +4,8 @@
#include "FindMyMouse.h" #include "FindMyMouse.h"
#include "trace.h" #include "trace.h"
#include "common/utils/game_mode.h" #include "common/utils/game_mode.h"
#include "common/utils/process_path.h"
#include "common/utils/excluded_apps.h"
#include <vector> #include <vector>
#ifdef COMPOSITION #ifdef COMPOSITION
@@ -45,6 +47,7 @@ protected:
void AfterMoveSonar() {} void AfterMoveSonar() {}
void SetSonarVisibility(bool visible) = delete; void SetSonarVisibility(bool visible) = delete;
void UpdateMouseSnooping(); void UpdateMouseSnooping();
bool IsForegroundAppExcluded();
protected: protected:
// Base class members you can access. // Base class members you can access.
@@ -65,6 +68,7 @@ protected:
int m_sonarZoomFactor = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM; int m_sonarZoomFactor = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM;
DWORD m_fadeDuration = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS; DWORD m_fadeDuration = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS;
int m_finalAlphaNumerator = FIND_MY_MOUSE_DEFAULT_OVERLAY_OPACITY; int m_finalAlphaNumerator = FIND_MY_MOUSE_DEFAULT_OVERLAY_OPACITY;
std::vector<std::wstring> m_excludedApps;
static constexpr int FinalAlphaDenominator = 100; static constexpr int FinalAlphaDenominator = 100;
winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr }; winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
@@ -479,6 +483,11 @@ void SuperSonar<D>::StartSonar()
return; return;
} }
if (IsForegroundAppExcluded())
{
return;
}
Logger::info("Focusing the sonar on the mouse cursor."); Logger::info("Focusing the sonar on the mouse cursor.");
Trace::MousePointerFocused(); Trace::MousePointerFocused();
// Cover the entire virtual screen. // Cover the entire virtual screen.
@@ -566,6 +575,25 @@ void SuperSonar<D>::UpdateMouseSnooping()
} }
} }
template<typename D>
bool SuperSonar<D>::IsForegroundAppExcluded()
{
if (m_excludedApps.size() < 1)
{
return false;
}
if (HWND foregroundApp{ GetForegroundWindow() })
{
auto processPath = get_process_path(foregroundApp);
CharUpperBuffW(processPath.data(), (DWORD)processPath.length());
return find_app_name_in_path(processPath, m_excludedApps);
}
else
{
return false;
}
}
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;
@@ -707,6 +735,7 @@ public:
m_fadeDuration = settings.animationDurationMs > 0 ? settings.animationDurationMs : 1; m_fadeDuration = settings.animationDurationMs > 0 ? settings.animationDurationMs : 1;
m_finalAlphaNumerator = settings.overlayOpacity; m_finalAlphaNumerator = settings.overlayOpacity;
m_sonarZoomFactor = settings.spotlightInitialZoom; m_sonarZoomFactor = settings.spotlightInitialZoom;
m_excludedApps = settings.excludedApps;
} }
else else
{ {
@@ -727,11 +756,12 @@ public:
m_sonarRadiusFloat = static_cast<float>(m_sonarRadius); m_sonarRadiusFloat = static_cast<float>(m_sonarRadius);
m_backgroundColor = localSettings.backgroundColor; m_backgroundColor = localSettings.backgroundColor;
m_spotlightColor = localSettings.spotlightColor; m_spotlightColor = localSettings.spotlightColor;
m_activationMethod = settings.activationMethod; m_activationMethod = localSettings.activationMethod;
m_doNotActivateOnGameMode = localSettings.doNotActivateOnGameMode; m_doNotActivateOnGameMode = localSettings.doNotActivateOnGameMode;
m_fadeDuration = localSettings.animationDurationMs > 0 ? localSettings.animationDurationMs : 1; m_fadeDuration = localSettings.animationDurationMs > 0 ? localSettings.animationDurationMs : 1;
m_finalAlphaNumerator = localSettings.overlayOpacity; m_finalAlphaNumerator = localSettings.overlayOpacity;
m_sonarZoomFactor = localSettings.spotlightInitialZoom; m_sonarZoomFactor = localSettings.spotlightInitialZoom;
m_excludedApps = localSettings.excludedApps;
UpdateMouseSnooping(); // For the shake mouse activation method UpdateMouseSnooping(); // For the shake mouse activation method
// Apply new settings to runtime composition objects. // Apply new settings to runtime composition objects.

View File

@@ -27,6 +27,7 @@ struct FindMyMouseSettings
int spotlightRadius = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_RADIUS; int spotlightRadius = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_RADIUS;
int animationDurationMs = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS; int animationDurationMs = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS;
int spotlightInitialZoom = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM; int spotlightInitialZoom = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM;
std::vector<std::wstring> excludedApps;
}; };
int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings); int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings);

View File

@@ -6,6 +6,7 @@
#include <thread> #include <thread>
#include <common/utils/logger_helper.h> #include <common/utils/logger_helper.h>
#include <common/utils/color.h> #include <common/utils/color.h>
#include <common/utils/string_utils.h>
namespace namespace
{ {
@@ -19,6 +20,7 @@ namespace
const wchar_t JSON_KEY_SPOTLIGHT_RADIUS[] = L"spotlight_radius"; 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_ANIMATION_DURATION_MS[] = L"animation_duration_ms";
const wchar_t JSON_KEY_SPOTLIGHT_INITIAL_ZOOM[] = L"spotlight_initial_zoom"; const wchar_t JSON_KEY_SPOTLIGHT_INITIAL_ZOOM[] = L"spotlight_initial_zoom";
const wchar_t JSON_KEY_EXCLUDED_APPS[] = L"excluded_apps";
} }
extern "C" IMAGE_DOS_HEADER __ImageBase; extern "C" IMAGE_DOS_HEADER __ImageBase;
@@ -273,6 +275,31 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{ {
Logger::warn("Failed to initialize Spotlight Initial Zoom from settings. Will use default value"); Logger::warn("Failed to initialize Spotlight Initial Zoom from settings. Will use default value");
} }
try
{
// Parse Excluded Apps
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_EXCLUDED_APPS);
std::wstring apps = jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE).c_str();
std::vector<std::wstring> excludedApps;
auto excludedUppercase = apps;
CharUpperBuffW(excludedUppercase.data(), (DWORD)excludedUppercase.length());
std::wstring_view view(excludedUppercase);
view = left_trim<wchar_t>(trim<wchar_t>(view));
while (!view.empty())
{
auto pos = (std::min)(view.find_first_of(L"\r\n"), view.length());
excludedApps.emplace_back(view.substr(0, pos));
view.remove_prefix(pos);
view = left_trim<wchar_t>(trim<wchar_t>(view));
}
findMyMouseSettings.excludedApps = excludedApps;
}
catch (...)
{
Logger::warn("Failed to initialize Excluded Apps from settings. Will use default value");
}
} }
else else
{ {

View File

@@ -3,6 +3,7 @@
#include <common/display/dpi_aware.h> #include <common/display/dpi_aware.h>
#include <common/utils/game_mode.h> #include <common/utils/game_mode.h>
#include <common/utils/excluded_apps.h>
#include <common/utils/resources.h> #include <common/utils/resources.h>
#include <common/utils/winapi_error.h> #include <common/utils/winapi_error.h>
#include <common/utils/process_path.h> #include <common/utils/process_path.h>
@@ -15,22 +16,6 @@ namespace NonLocalizable
const static wchar_t* WINDOW_IS_PINNED_PROP = L"AlwaysOnTop_Pinned"; const static wchar_t* WINDOW_IS_PINNED_PROP = L"AlwaysOnTop_Pinned";
} }
// TODO: move to common utils
bool find_app_name_in_path(const std::wstring& where, const std::vector<std::wstring>& what)
{
for (const auto& row : what)
{
const auto pos = where.rfind(row);
const auto last_slash = where.rfind('\\');
//Check that row occurs in where, and its last occurrence contains in itself the first character after the last backslash.
if (pos != std::wstring::npos && pos <= last_slash + 1 && pos + row.length() > last_slash)
{
return true;
}
}
return false;
}
bool isExcluded(HWND window) bool isExcluded(HWND window)
{ {
auto processPath = get_process_path(window); auto processPath = get_process_path(window);

View File

@@ -5,6 +5,7 @@
#include <common/display/dpi_aware.h> #include <common/display/dpi_aware.h>
#include <common/utils/process_path.h> #include <common/utils/process_path.h>
#include <common/utils/window.h> #include <common/utils/window.h>
#include <common/utils/excluded_apps.h>
#include <array> #include <array>
#include <complex> #include <complex>
@@ -20,20 +21,6 @@ namespace NonLocalizable
const wchar_t SplashClassName[] = L"MsoSplash"; const wchar_t SplashClassName[] = L"MsoSplash";
} }
bool find_app_name_in_path(const std::wstring& where, const std::vector<std::wstring>& what)
{
for (const auto& row : what)
{
const auto pos = where.rfind(row);
const auto last_slash = where.rfind('\\');
//Check that row occurs in where, and its last occurrence contains in itself the first character after the last backslash.
if (pos != std::wstring::npos && pos <= last_slash + 1 && pos + row.length() > last_slash)
{
return true;
}
}
return false;
}
namespace namespace
{ {
bool IsZonableByProcessPath(const std::wstring& processPath, const std::vector<std::wstring>& excludedApps) bool IsZonableByProcessPath(const std::wstring& processPath, const std::vector<std::wstring>& excludedApps)

View File

@@ -32,6 +32,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("spotlight_initial_zoom")] [JsonPropertyName("spotlight_initial_zoom")]
public IntProperty SpotlightInitialZoom { get; set; } public IntProperty SpotlightInitialZoom { get; set; }
[JsonPropertyName("excluded_apps")]
public StringProperty ExcludedApps { get; set; }
public FindMyMouseProperties() public FindMyMouseProperties()
{ {
ActivationMethod = new IntProperty(0); ActivationMethod = new IntProperty(0);
@@ -42,6 +45,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
SpotlightRadius = new IntProperty(100); SpotlightRadius = new IntProperty(100);
AnimationDurationMs = new IntProperty(500); AnimationDurationMs = new IntProperty(500);
SpotlightInitialZoom = new IntProperty(9); SpotlightInitialZoom = new IntProperty(9);
ExcludedApps = new StringProperty();
} }
} }
} }

View File

@@ -60,6 +60,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
_findMyMouseSpotlightRadius = FindMyMouseSettingsConfig.Properties.SpotlightRadius.Value; _findMyMouseSpotlightRadius = FindMyMouseSettingsConfig.Properties.SpotlightRadius.Value;
_findMyMouseAnimationDurationMs = FindMyMouseSettingsConfig.Properties.AnimationDurationMs.Value; _findMyMouseAnimationDurationMs = FindMyMouseSettingsConfig.Properties.AnimationDurationMs.Value;
_findMyMouseSpotlightInitialZoom = FindMyMouseSettingsConfig.Properties.SpotlightInitialZoom.Value; _findMyMouseSpotlightInitialZoom = FindMyMouseSettingsConfig.Properties.SpotlightInitialZoom.Value;
_findMyMouseExcludedApps = FindMyMouseSettingsConfig.Properties.ExcludedApps.Value;
if (mouseHighlighterSettingsRepository == null) if (mouseHighlighterSettingsRepository == null)
{ {
@@ -266,6 +267,24 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
} }
} }
public string FindMyMouseExcludedApps
{
get
{
return _findMyMouseExcludedApps;
}
set
{
if (value != _findMyMouseExcludedApps)
{
_findMyMouseExcludedApps = value;
FindMyMouseSettingsConfig.Properties.ExcludedApps.Value = value;
NotifyFindMyMousePropertyChanged();
}
}
}
public void NotifyFindMyMousePropertyChanged([CallerMemberName] string propertyName = null) public void NotifyFindMyMousePropertyChanged([CallerMemberName] string propertyName = null)
{ {
OnPropertyChanged(propertyName); OnPropertyChanged(propertyName);
@@ -613,6 +632,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
private int _findMyMouseSpotlightRadius; private int _findMyMouseSpotlightRadius;
private int _findMyMouseAnimationDurationMs; private int _findMyMouseAnimationDurationMs;
private int _findMyMouseSpotlightInitialZoom; private int _findMyMouseSpotlightInitialZoom;
private string _findMyMouseExcludedApps;
private bool _isMouseHighlighterEnabled; private bool _isMouseHighlighterEnabled;
private string _highlighterLeftButtonClickColor; private string _highlighterLeftButtonClickColor;

View File

@@ -1775,6 +1775,15 @@ From there, simply click on a Markdown file, PDF file or SVG icon in the File Ex
<value>Shake mouse</value> <value>Shake mouse</value>
<comment>Mouse is the hardware peripheral.</comment> <comment>Mouse is the hardware peripheral.</comment>
</data> </data>
<data name="MouseUtils_FindMyMouse_ExcludedApps.Description" xml:space="preserve">
<value>Prevents module activation when an excluded application is the foreground application</value>
</data>
<data name="MouseUtils_FindMyMouse_ExcludedApps.Header" xml:space="preserve">
<value>Excluded apps</value>
</data>
<data name="MouseUtils_FindMyMouse_ExcludedApps_TextBoxControl.PlaceholderText" xml:space="preserve">
<value>Example: outlook.exe</value>
</data>
<data name="MouseUtils_Prevent_Activation_On_Game_Mode.Content" xml:space="preserve"> <data name="MouseUtils_Prevent_Activation_On_Game_Mode.Content" xml:space="preserve">
<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>

View File

@@ -93,6 +93,23 @@
</StackPanel> </StackPanel>
</controls:SettingExpander.Content> </controls:SettingExpander.Content>
</controls:SettingExpander> </controls:SettingExpander>
<controls:SettingExpander IsExpanded="False">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="MouseUtils_FindMyMouse_ExcludedApps" Icon="&#xECE4;" Style="{StaticResource ExpanderHeaderSettingStyle}"/>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<TextBox x:Uid="MouseUtils_FindMyMouse_ExcludedApps_TextBoxControl"
Margin="{StaticResource ExpanderSettingMargin}"
Text="{x:Bind Mode=TwoWay, Path=ViewModel.FindMyMouseExcludedApps, UpdateSourceTrigger=PropertyChanged}"
ScrollViewer.VerticalScrollBarVisibility ="Visible"
ScrollViewer.VerticalScrollMode="Enabled"
ScrollViewer.IsVerticalRailEnabled="True"
TextWrapping="Wrap"
AcceptsReturn="True"
MinWidth="240"
MinHeight="160" />
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup> </controls:SettingsGroup>
<controls:SettingsGroup x:Uid="MouseUtils_MouseHighlighter"> <controls:SettingsGroup x:Uid="MouseUtils_MouseHighlighter">