Mouse Utils - Mouse Highlighter (#14496)

* New PowerToys template

* Add CppWinRt to empty PowerToy

* Add Settings reference to empty PowerToy

* Use proper output dir

* Proper WindowsTargetPlatformVersion

* Add filters to vcxproj

* Proper resource file generation

* Add MouseHighlighter proof of concept code

* Abstract implementation into a struct

* Enable module

* Disable module

* Add enable module to settings page

* Can change the hotkey in settings

* Remove remaining boilerplate code

* Add logging

* Add telemetry

* Add Oobe entry

* Add installer instructions

* Add dll to pipelines

* fix spellchecker

* Add more configurability

* Make settings a bit prettier

* Fix spellchecker

* Fix wrong default fade timers

* Fix user facing strings

* Tweak default duration values

* Fix to appear in every virtual desktop

* [Mouse Highlighter] Show highlight on mouse drag (#14529)

* [Mouse Highlighter]show pointer on mouse drag

* fix spellchecker

* [MU] UI tweaks (#14544)

* UI tweaks

* Update Resources.resw

* Updated text strings

* fix spellcheck

Co-authored-by: Laute <Niels.Laute@philips.com>

* tweak default values

* PR feedback: use wstring_view

* PR feedback: Log error on json error

* PR feedback: don't throw 1

* PR feedback: fix copy-pasta leftColor->rightColor

* PR feedback:Add another error message on exception

* PR feedback: add todo to use commons/utils/json.h

Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Laute <Niels.Laute@philips.com>
This commit is contained in:
Jaime Bernardo
2021-11-22 13:31:31 +00:00
committed by GitHub
parent 0dae5d0402
commit 2d5276f742
36 changed files with 1726 additions and 50 deletions

View File

@@ -191,6 +191,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
}
private bool mouseHighlighter = true;
[JsonPropertyName("MouseHighlighter")]
public bool MouseHighlighter
{
get => mouseHighlighter;
set
{
if (mouseHighlighter != value)
{
LogTelemetryEvent(value);
mouseHighlighter = value;
}
}
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);

View File

@@ -0,0 +1,39 @@
// 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.Drawing;
using System.Globalization;
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
{
public static class SettingsUtilities
{
public static string ToRGBHex(string color)
{
if (color == null)
{
return "#FFFFFF";
}
// Using InvariantCulture as these are expected to be hex codes.
bool success = int.TryParse(
color.Replace("#", string.Empty),
System.Globalization.NumberStyles.HexNumber,
CultureInfo.InvariantCulture,
out int argb);
if (success)
{
Color clr = Color.FromArgb(argb);
return "#" + clr.R.ToString("X2", CultureInfo.InvariantCulture) +
clr.G.ToString("X2", CultureInfo.InvariantCulture) +
clr.B.ToString("X2", CultureInfo.InvariantCulture);
}
else
{
return "#FFFFFF";
}
}
}
}

View File

@@ -0,0 +1,43 @@
// 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 MouseHighlighterProperties
{
[JsonPropertyName("activation_shortcut")]
public HotkeySettings ActivationShortcut { get; set; }
[JsonPropertyName("left_button_click_color")]
public StringProperty LeftButtonClickColor { get; set; }
[JsonPropertyName("right_button_click_color")]
public StringProperty RightButtonClickColor { get; set; }
[JsonPropertyName("highlight_opacity")]
public IntProperty HighlightOpacity { get; set; }
[JsonPropertyName("highlight_radius")]
public IntProperty HighlightRadius { get; set; }
[JsonPropertyName("highlight_fade_delay_ms")]
public IntProperty HighlightFadeDelayMs { get; set; }
[JsonPropertyName("highlight_fade_duration_ms")]
public IntProperty HighlightFadeDurationMs { get; set; }
public MouseHighlighterProperties()
{
ActivationShortcut = new HotkeySettings(true, false, false, true, 0x48);
LeftButtonClickColor = new StringProperty("#FFFF00");
RightButtonClickColor = new StringProperty("#0000FF");
HighlightOpacity = new IntProperty(160);
HighlightRadius = new IntProperty(20);
HighlightFadeDelayMs = new IntProperty(500);
HighlightFadeDurationMs = new IntProperty(250);
}
}
}

View File

@@ -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 MouseHighlighterSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "MouseHighlighter";
[JsonPropertyName("properties")]
public MouseHighlighterProperties Properties { get; set; }
public MouseHighlighterSettings()
{
Name = ModuleName;
Properties = new MouseHighlighterProperties();
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;
}
}
}

View File

@@ -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 MouseHighlighterSettingsIPCMessage
{
[JsonPropertyName("powertoys")]
public SndMouseHighlighterSettings Powertoys { get; set; }
public MouseHighlighterSettingsIPCMessage()
{
}
public MouseHighlighterSettingsIPCMessage(SndMouseHighlighterSettings settings)
{
this.Powertoys = settings;
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}

View File

@@ -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 SndMouseHighlighterSettings
{
[JsonPropertyName("MouseHighlighter")]
public MouseHighlighterSettings MouseHighlighter { get; set; }
public SndMouseHighlighterSettings()
{
}
public SndMouseHighlighterSettings(MouseHighlighterSettings settings)
{
MouseHighlighter = settings;
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}

View File

@@ -554,7 +554,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
// The fallback value is based on ToRGBHex's behavior, which returns
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
// This extra handling is added here to deal with FxCop warnings.
value = (value != null) ? ToRGBHex(value) : "#FFFFFF";
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
if (!value.Equals(_zoneHighlightColor, StringComparison.OrdinalIgnoreCase))
{
_zoneHighlightColor = value;
@@ -576,7 +576,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
// The fallback value is based on ToRGBHex's behavior, which returns
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
// This extra handling is added here to deal with FxCop warnings.
value = (value != null) ? ToRGBHex(value) : "#FFFFFF";
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
if (!value.Equals(_zoneBorderColor, StringComparison.OrdinalIgnoreCase))
{
_zoneBorderColor = value;
@@ -598,7 +598,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
// The fallback value is based on ToRGBHex's behavior, which returns
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
// This extra handling is added here to deal with FxCop warnings.
value = (value != null) ? ToRGBHex(value) : "#FFFFFF";
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
if (!value.Equals(_zoneInActiveColor, StringComparison.OrdinalIgnoreCase))
{
_zoneInActiveColor = value;
@@ -753,27 +753,5 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
OnPropertyChanged(propertyName);
SettingsUtils.SaveSettings(Settings.ToJsonString(), GetSettingsSubPath());
}
private static string ToRGBHex(string color)
{
// Using InvariantCulture as these are expected to be hex codes.
bool success = int.TryParse(
color.Replace("#", string.Empty),
System.Globalization.NumberStyles.HexNumber,
CultureInfo.InvariantCulture,
out int argb);
if (success)
{
Color clr = Color.FromArgb(argb);
return "#" + clr.R.ToString("X2", CultureInfo.InvariantCulture) +
clr.G.ToString("X2", CultureInfo.InvariantCulture) +
clr.B.ToString("X2", CultureInfo.InvariantCulture);
}
else
{
return "#FFFFFF";
}
}
}
}

View File

@@ -17,7 +17,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
private FindMyMouseSettings FindMyMouseSettingsConfig { get; set; }
public MouseUtilsViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<FindMyMouseSettings> findMyMouseSettingsRepository, Func<string, int> ipcMSGCallBackFunc)
private MouseHighlighterSettings MouseHighlighterSettingsConfig { get; set; }
public MouseUtilsViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<FindMyMouseSettings> findMyMouseSettingsRepository, ISettingsRepository<MouseHighlighterSettings> mouseHighlighterSettingsRepository, Func<string, int> ipcMSGCallBackFunc)
{
SettingsUtils = settingsUtils;
@@ -31,6 +33,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
_isFindMyMouseEnabled = GeneralSettingsConfig.Enabled.FindMyMouse;
_isMouseHighlighterEnabled = GeneralSettingsConfig.Enabled.MouseHighlighter;
// 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)
@@ -41,6 +45,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
FindMyMouseSettingsConfig = findMyMouseSettingsRepository.SettingsConfig;
_findMyMouseDoNotActivateOnGameMode = FindMyMouseSettingsConfig.Properties.DoNotActivateOnGameMode.Value;
if (mouseHighlighterSettingsRepository == null)
{
throw new ArgumentNullException(nameof(mouseHighlighterSettingsRepository));
}
MouseHighlighterSettingsConfig = mouseHighlighterSettingsRepository.SettingsConfig;
string leftClickColor = MouseHighlighterSettingsConfig.Properties.LeftButtonClickColor.Value;
_highlighterLeftButtonClickColor = !string.IsNullOrEmpty(leftClickColor) ? leftClickColor : "#FFFF00";
string rightClickColor = MouseHighlighterSettingsConfig.Properties.RightButtonClickColor.Value;
_highlighterRightButtonClickColor = !string.IsNullOrEmpty(rightClickColor) ? rightClickColor : "#0000FF";
_highlighterOpacity = MouseHighlighterSettingsConfig.Properties.HighlightOpacity.Value;
_highlighterRadius = MouseHighlighterSettingsConfig.Properties.HighlightRadius.Value;
_highlightFadeDelayMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDelayMs.Value;
_highlightFadeDurationMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDurationMs.Value;
// set the callback functions value to handle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
}
@@ -93,9 +114,180 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
SettingsUtils.SaveSettings(FindMyMouseSettingsConfig.ToJsonString(), FindMyMouseSettings.ModuleName);
}
public bool IsMouseHighlighterEnabled
{
get => _isMouseHighlighterEnabled;
set
{
if (_isMouseHighlighterEnabled != value)
{
_isMouseHighlighterEnabled = value;
GeneralSettingsConfig.Enabled.MouseHighlighter = value;
OnPropertyChanged(nameof(_isMouseHighlighterEnabled));
OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(outgoing.ToString());
NotifyMouseHighlighterPropertyChanged();
}
}
}
public HotkeySettings MouseHighlighterActivationShortcut
{
get
{
return MouseHighlighterSettingsConfig.Properties.ActivationShortcut;
}
set
{
if (MouseHighlighterSettingsConfig.Properties.ActivationShortcut != value)
{
MouseHighlighterSettingsConfig.Properties.ActivationShortcut = value;
NotifyMouseHighlighterPropertyChanged();
}
}
}
public string MouseHighlighterLeftButtonClickColor
{
get
{
return _highlighterLeftButtonClickColor;
}
set
{
// The fallback value is based on ToRGBHex's behavior, which returns
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
// This extra handling is added here to deal with FxCop warnings.
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
if (!value.Equals(_highlighterLeftButtonClickColor, StringComparison.OrdinalIgnoreCase))
{
_highlighterLeftButtonClickColor = value;
MouseHighlighterSettingsConfig.Properties.LeftButtonClickColor.Value = value;
NotifyMouseHighlighterPropertyChanged();
}
}
}
public string MouseHighlighterRightButtonClickColor
{
get
{
return _highlighterRightButtonClickColor;
}
set
{
// The fallback value is based on ToRGBHex's behavior, which returns
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
// This extra handling is added here to deal with FxCop warnings.
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
if (!value.Equals(_highlighterRightButtonClickColor, StringComparison.OrdinalIgnoreCase))
{
_highlighterRightButtonClickColor = value;
MouseHighlighterSettingsConfig.Properties.RightButtonClickColor.Value = value;
NotifyMouseHighlighterPropertyChanged();
}
}
}
public int MouseHighlighterOpacity
{
get
{
return _highlighterOpacity;
}
set
{
if (value != _highlighterOpacity)
{
_highlighterOpacity = value;
MouseHighlighterSettingsConfig.Properties.HighlightOpacity.Value = value;
NotifyMouseHighlighterPropertyChanged();
}
}
}
public int MouseHighlighterRadius
{
get
{
return _highlighterRadius;
}
set
{
if (value != _highlighterRadius)
{
_highlighterRadius = value;
MouseHighlighterSettingsConfig.Properties.HighlightRadius.Value = value;
NotifyMouseHighlighterPropertyChanged();
}
}
}
public int MouseHighlighterFadeDelayMs
{
get
{
return _highlightFadeDelayMs;
}
set
{
if (value != _highlightFadeDelayMs)
{
_highlightFadeDelayMs = value;
MouseHighlighterSettingsConfig.Properties.HighlightFadeDelayMs.Value = value;
NotifyMouseHighlighterPropertyChanged();
}
}
}
public int MouseHighlighterFadeDurationMs
{
get
{
return _highlightFadeDurationMs;
}
set
{
if (value != _highlightFadeDurationMs)
{
_highlightFadeDurationMs = value;
MouseHighlighterSettingsConfig.Properties.HighlightFadeDurationMs.Value = value;
NotifyMouseHighlighterPropertyChanged();
}
}
}
public void NotifyMouseHighlighterPropertyChanged([CallerMemberName] string propertyName = null)
{
OnPropertyChanged(propertyName);
SndMouseHighlighterSettings outsettings = new SndMouseHighlighterSettings(MouseHighlighterSettingsConfig);
SndModuleSettings<SndMouseHighlighterSettings> ipcMessage = new SndModuleSettings<SndMouseHighlighterSettings>(outsettings);
SendConfigMSG(ipcMessage.ToJsonString());
SettingsUtils.SaveSettings(MouseHighlighterSettingsConfig.ToJsonString(), MouseHighlighterSettings.ModuleName);
}
private Func<string, int> SendConfigMSG { get; }
private bool _isFindMyMouseEnabled;
private bool _findMyMouseDoNotActivateOnGameMode;
private bool _isMouseHighlighterEnabled;
private string _highlighterLeftButtonClickColor;
private string _highlighterRightButtonClickColor;
private int _highlighterOpacity;
private int _highlighterRadius;
private int _highlightFadeDelayMs;
private int _highlightFadeDurationMs;
}
}