From af8366f0fe1f6abe7878b1f7f70a38390a930a26 Mon Sep 17 00:00:00 2001 From: Jaime Bernardo Date: Mon, 25 Oct 2021 19:39:48 +0100 Subject: [PATCH] [FindMyMouse]Do not activate on game mode (#13990) * [FindMyMouse] Do not activate on game mode * Add settings scaffolding * fix spellchecker * Address PR comments * Adress UI feedback --- .github/actions/spell-check/expect.txt | 1 + PowerToys.sln | 1 + src/common/utils/game_mode.h | 12 +++++ .../MouseUtils/FindMyMouse/FindMyMouse.cpp | 14 +++++ .../MouseUtils/FindMyMouse/FindMyMouse.h | 2 +- .../MouseUtils/FindMyMouse/dllmain.cpp | 38 +++++++++++++ .../FindMyMouseProperties.cs | 19 +++++++ .../FindMyMouseSettings.cs | 35 ++++++++++++ .../FindMyMouseSettingsIPCMessage.cs | 29 ++++++++++ .../SndFindMyMouseSettings.cs | 29 ++++++++++ .../ViewModels/MouseUtilsViewModel.cs | 53 +++++++++++++++++-- .../Strings/en-us/Resources.resw | 4 ++ .../Views/MouseUtilsPage.xaml | 21 +++++--- .../Views/MouseUtilsPage.xaml.cs | 2 +- 14 files changed, 248 insertions(+), 12 deletions(-) create mode 100644 src/common/utils/game_mode.h create mode 100644 src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseProperties.cs create mode 100644 src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseSettings.cs create mode 100644 src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseSettingsIPCMessage.cs create mode 100644 src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/SndFindMyMouseSettings.cs diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 6be388004b..09f024255e 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1713,6 +1713,7 @@ QUERYOPEN QUEUESYNC Quickime QUICKLAYOUTSWITCH +QUNS qwertyuiopasdfghjklzxcvbnm qword qwrtyuiopsghjklzxvnm diff --git a/PowerToys.sln b/PowerToys.sln index 4b86d4bda6..e185f09f71 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -267,6 +267,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643 src\common\utils\EventLocker.h = src\common\utils\EventLocker.h src\common\utils\EventWaiter.h = src\common\utils\EventWaiter.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\HDropIterator.h = src\common\utils\HDropIterator.h src\common\utils\HttpClient.h = src\common\utils\HttpClient.h src\common\utils\json.h = src\common\utils\json.h diff --git a/src/common/utils/game_mode.h b/src/common/utils/game_mode.h new file mode 100644 index 0000000000..05e4e7dd1a --- /dev/null +++ b/src/common/utils/game_mode.h @@ -0,0 +1,12 @@ +#pragma once +#include + +inline bool detect_game_mode() +{ + QUERY_USER_NOTIFICATION_STATE notification_state; + if (SHQueryUserNotificationState(¬ification_state) != S_OK) + { + return false; + } + return (notification_state == QUNS_RUNNING_D3D_FULL_SCREEN); +} diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp index 4af7906e43..33e182e433 100644 --- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp +++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp @@ -3,6 +3,7 @@ #include "pch.h" #include "FindMyMouse.h" #include "trace.h" +#include "common/utils/game_mode.h" #ifdef COMPOSITION namespace winrt @@ -18,6 +19,8 @@ namespace ABI } #endif +bool m_doNotActivateOnGameMode = true; + #pragma region Super_Sonar_Base_Code template @@ -250,6 +253,12 @@ void SuperSonar::OnSonarInput(WPARAM flags, HRAWINPUT hInput) template void SuperSonar::OnSonarKeyboardInput(RAWINPUT const& input) { + // Don't activate if game mode is on. + if (m_doNotActivateOnGameMode && detect_game_mode()) + { + return; + } + if (input.data.keyboard.VKey != VK_CONTROL) { StopSonar(); @@ -777,6 +786,11 @@ bool FindMyMouseIsEnabled() return (m_sonar != nullptr); } +void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate) +{ + m_doNotActivateOnGameMode = doNotActivate; +} + // Based on SuperSonar's original wWinMain. int FindMyMouseMain(HINSTANCE hinst) { diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h index feaa5d121b..d5c4653d16 100644 --- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h +++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h @@ -3,4 +3,4 @@ int FindMyMouseMain(HINSTANCE hinst); void FindMyMouseDisable(); bool FindMyMouseIsEnabled(); - +void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate); diff --git a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp index 26ebbb8994..495d74a4b2 100644 --- a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp +++ b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp @@ -6,6 +6,14 @@ #include #include + +namespace +{ + const wchar_t JSON_KEY_PROPERTIES[] = L"properties"; + const wchar_t JSON_KEY_VALUE[] = L"value"; + const wchar_t JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE[] = L"do_not_activate_on_game_mode"; +} + extern "C" IMAGE_DOS_HEADER __ImageBase; HMODULE m_hModule; @@ -43,6 +51,9 @@ private: // Load initial settings from the persisted values. void init_settings(); + // Helper function to extract the settings + void parse_settings(PowerToysSettings::PowerToyValues& settings); + public: // Constructor FindMyMouse() @@ -96,6 +107,8 @@ public: PowerToysSettings::PowerToyValues values = PowerToysSettings::PowerToyValues::from_json_string(config, get_key()); + parse_settings(values); + values.save_to_settings_file(); } catch (std::exception&) @@ -135,6 +148,7 @@ void FindMyMouse::init_settings() // Load and parse the settings file for this PowerToy. PowerToysSettings::PowerToyValues settings = PowerToysSettings::PowerToyValues::load_from_settings_file(FindMyMouse::get_key()); + parse_settings(settings); } catch (std::exception&) { @@ -142,6 +156,30 @@ void FindMyMouse::init_settings() } } +void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings) +{ + FindMyMouseSetDoNotActivateOnGameMode(true); + + auto settingsObject = settings.get_raw_json(); + if (settingsObject.GetView().Size()) + { + try + { + auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE); + FindMyMouseSetDoNotActivateOnGameMode((bool)jsonPropertiesObject.GetNamedBoolean(JSON_KEY_VALUE)); + } + catch (...) + { + Logger::warn("Failed to get 'do not activate on game mode' setting"); + } + } + else + { + Logger::info("Find My Mouse settings are empty"); + } +} + + extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create() { return new FindMyMouse(); diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseProperties.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseProperties.cs new file mode 100644 index 0000000000..65cf20cb8e --- /dev/null +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseProperties.cs @@ -0,0 +1,19 @@ +// 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 System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Library +{ + public class FindMyMouseProperties + { + [JsonPropertyName("do_not_activate_on_game_mode")] + public BoolProperty DoNotActivateOnGameMode { get; set; } + + public FindMyMouseProperties() + { + DoNotActivateOnGameMode = new BoolProperty(true); + } + } +} diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseSettings.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseSettings.cs new file mode 100644 index 0000000000..2f714cce1d --- /dev/null +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseSettings.cs @@ -0,0 +1,35 @@ +// 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 System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Library.Interfaces; + +namespace Microsoft.PowerToys.Settings.UI.Library +{ + public class FindMyMouseSettings : BasePTModuleSettings, ISettingsConfig + { + public const string ModuleName = "Find My Mouse"; + + [JsonPropertyName("properties")] + public FindMyMouseProperties Properties { get; set; } + + public FindMyMouseSettings() + { + Name = ModuleName; + Properties = new FindMyMouseProperties(); + Version = "1.0"; + } + + public string GetModuleName() + { + return Name; + } + + // This can be utilized in the future if the settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; + } + } +} diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseSettingsIPCMessage.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseSettingsIPCMessage.cs new file mode 100644 index 0000000000..1ae2db6f2b --- /dev/null +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/FindMyMouseSettingsIPCMessage.cs @@ -0,0 +1,29 @@ +// 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 System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Library +{ + public class FindMyMouseSettingsIPCMessage + { + [JsonPropertyName("powertoys")] + public SndFindMyMouseSettings Powertoys { get; set; } + + public FindMyMouseSettingsIPCMessage() + { + } + + public FindMyMouseSettingsIPCMessage(SndFindMyMouseSettings settings) + { + this.Powertoys = settings; + } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/SndFindMyMouseSettings.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/SndFindMyMouseSettings.cs new file mode 100644 index 0000000000..37502e2ed3 --- /dev/null +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/SndFindMyMouseSettings.cs @@ -0,0 +1,29 @@ +// 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 System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Library +{ + public class SndFindMyMouseSettings + { + [JsonPropertyName("FindMyMouse")] + public FindMyMouseSettings FindMyMouse { get; set; } + + public SndFindMyMouseSettings() + { + } + + public SndFindMyMouseSettings(FindMyMouseSettings settings) + { + FindMyMouse = settings; + } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/MouseUtilsViewModel.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/MouseUtilsViewModel.cs index 6aeadef00d..5faec966f7 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/MouseUtilsViewModel.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/MouseUtilsViewModel.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Runtime.CompilerServices; using Microsoft.PowerToys.Settings.UI.Library.Helpers; using Microsoft.PowerToys.Settings.UI.Library.Interfaces; @@ -10,10 +11,16 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels { public class MouseUtilsViewModel : Observable { + private ISettingsUtils SettingsUtils { get; set; } + private GeneralSettings GeneralSettingsConfig { get; set; } - public MouseUtilsViewModel(ISettingsRepository settingsRepository, Func ipcMSGCallBackFunc) + private FindMyMouseSettings FindMyMouseSettingsConfig { get; set; } + + public MouseUtilsViewModel(ISettingsUtils settingsUtils, ISettingsRepository settingsRepository, ISettingsRepository findMyMouseSettingsRepository, Func ipcMSGCallBackFunc) { + SettingsUtils = settingsUtils; + // To obtain the general settings configurations of PowerToys Settings. if (settingsRepository == null) { @@ -24,7 +31,17 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels _isFindMyMouseEnabled = GeneralSettingsConfig.Enabled.FindMyMouse; - // set the callback functions value to hangle outgoing IPC message. + // To obtain the find my mouse settings, if the file exists. + // If not, to create a file with the default settings and to return the default configurations. + if (findMyMouseSettingsRepository == null) + { + throw new ArgumentNullException(nameof(findMyMouseSettingsRepository)); + } + + FindMyMouseSettingsConfig = findMyMouseSettingsRepository.SettingsConfig; + _findMyMouseDoNotActivateOnGameMode = FindMyMouseSettingsConfig.Properties.DoNotActivateOnGameMode.Value; + + // set the callback functions value to handle outgoing IPC message. SendConfigMSG = ipcMSGCallBackFunc; } @@ -43,14 +60,42 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig); SendConfigMSG(outgoing.ToString()); - // TODO: Implement when this module has properties. - // NotifyPropertyChanged(); + NotifyFindMyMousePropertyChanged(); } } } + public bool FindMyMouseDoNotActivateOnGameMode + { + get + { + return _findMyMouseDoNotActivateOnGameMode; + } + + set + { + if (_findMyMouseDoNotActivateOnGameMode != value) + { + _findMyMouseDoNotActivateOnGameMode = value; + FindMyMouseSettingsConfig.Properties.DoNotActivateOnGameMode.Value = value; + NotifyFindMyMousePropertyChanged(); + } + } + } + + public void NotifyFindMyMousePropertyChanged([CallerMemberName] string propertyName = null) + { + OnPropertyChanged(propertyName); + + SndFindMyMouseSettings outsettings = new SndFindMyMouseSettings(FindMyMouseSettingsConfig); + SndModuleSettings ipcMessage = new SndModuleSettings(outsettings); + SendConfigMSG(ipcMessage.ToJsonString()); + SettingsUtils.SaveSettings(FindMyMouseSettingsConfig.ToJsonString(), FindMyMouseSettings.ModuleName); + } + private Func SendConfigMSG { get; } private bool _isFindMyMouseEnabled; + private bool _findMyMouseDoNotActivateOnGameMode; } } diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw index ade1c0774b..d43d39859f 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw @@ -1702,4 +1702,8 @@ From there, simply click on a Markdown file, PDF file or SVG icon in the File Ex Press the Left Control key twice to focus the mouse pointer. "Left Control" is a keyboard key. + + Do not activate when Game Mode is on + "Game mode" is the Windows feature to prevent notification when playing a game. + \ No newline at end of file diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/MouseUtilsPage.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/MouseUtilsPage.xaml index 64627b24c6..e25ed90096 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/MouseUtilsPage.xaml +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/MouseUtilsPage.xaml @@ -14,12 +14,21 @@ - - - - - - + + + + + + + + + + + + diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/MouseUtilsPage.xaml.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/MouseUtilsPage.xaml.cs index bbc294fad9..b2e8867dd3 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/MouseUtilsPage.xaml.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/MouseUtilsPage.xaml.cs @@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public MouseUtilsPage() { var settingsUtils = new SettingsUtils(); - ViewModel = new MouseUtilsViewModel(SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); + ViewModel = new MouseUtilsViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; InitializeComponent(); }