mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-01-18 22:43:31 +08:00
[MouseHighlighter]Add always-on pointer (#27186)
* [MouseHighlighter]Add always pointer Make color pick UI ARGB Delete Opacity setting * Fix opacity and color Fix "always color" incorrectly initialized Revert default opacity to 65%, which was unintentionally lowered to 25% when changing to percent * Fix crash when opening MouseUtils settings page Migration code was bugged, made malformed json and led to settings page crash. * Implement migration in module side
This commit is contained in:
parent
a99b2e0bc0
commit
a71411d931
@ -19,3 +19,23 @@ inline bool checkValidRGB(std::wstring_view hex, uint8_t* R, uint8_t* G, uint8_t
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// helper function to get the ARGB from a #FFFFFFFF string.
|
||||
inline bool checkValidARGB(std::wstring_view hex, uint8_t* A, uint8_t* R, uint8_t* G, uint8_t* B)
|
||||
{
|
||||
if (hex.length() != 9)
|
||||
return false;
|
||||
hex = hex.substr(1, 8); // remove #
|
||||
for (auto& c : hex)
|
||||
{
|
||||
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (swscanf_s(hex.data(), L"%2hhx%2hhx%2hhx%2hhx", A, R, G, B) != 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ private:
|
||||
enum class MouseButton
|
||||
{
|
||||
Left,
|
||||
Right
|
||||
Right,
|
||||
None
|
||||
};
|
||||
|
||||
void DestroyHighlighter();
|
||||
@ -42,6 +43,7 @@ private:
|
||||
void AddDrawingPoint(MouseButton button);
|
||||
void UpdateDrawingPointPosition(MouseButton button);
|
||||
void StartDrawingPointFading(MouseButton button);
|
||||
void ClearDrawingPoint(MouseButton button);
|
||||
void ClearDrawing();
|
||||
HHOOK m_mouseHook = NULL;
|
||||
static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) noexcept;
|
||||
@ -62,6 +64,12 @@ private:
|
||||
|
||||
winrt::CompositionSpriteShape m_leftPointer{ nullptr };
|
||||
winrt::CompositionSpriteShape m_rightPointer{ nullptr };
|
||||
winrt::CompositionSpriteShape m_alwaysPointer{ nullptr };
|
||||
|
||||
bool m_leftPointerEnabled = true;
|
||||
bool m_rightPointerEnabled = true;
|
||||
bool m_alwaysPointerEnabled = true;
|
||||
|
||||
bool m_leftButtonPressed = false;
|
||||
bool m_rightButtonPressed = false;
|
||||
|
||||
@ -75,6 +83,7 @@ private:
|
||||
|
||||
winrt::Windows::UI::Color m_leftClickColor = MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR;
|
||||
winrt::Windows::UI::Color m_rightClickColor = MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR;
|
||||
winrt::Windows::UI::Color m_alwaysColor = MOUSE_HIGHLIGHTER_DEFAULT_ALWAYS_COLOR;
|
||||
};
|
||||
|
||||
Highlighter* Highlighter::instance = nullptr;
|
||||
@ -132,18 +141,23 @@ void Highlighter::AddDrawingPoint(MouseButton button)
|
||||
auto circleGeometry = m_compositor.CreateEllipseGeometry();
|
||||
circleGeometry.Radius({ m_radius, m_radius });
|
||||
auto circleShape = m_compositor.CreateSpriteShape(circleGeometry);
|
||||
circleShape.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y )});
|
||||
circleShape.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y) });
|
||||
if (button == MouseButton::Left)
|
||||
{
|
||||
circleShape.FillBrush(m_compositor.CreateColorBrush(m_leftClickColor));
|
||||
m_leftPointer = circleShape;
|
||||
}
|
||||
else
|
||||
else if (button == MouseButton::Right)
|
||||
{
|
||||
//right
|
||||
circleShape.FillBrush(m_compositor.CreateColorBrush(m_rightClickColor));
|
||||
m_rightPointer = circleShape;
|
||||
}
|
||||
else
|
||||
{
|
||||
// always
|
||||
circleShape.FillBrush(m_compositor.CreateColorBrush(m_alwaysColor));
|
||||
m_alwaysPointer = circleShape;
|
||||
}
|
||||
m_shape.Shapes().Append(circleShape);
|
||||
|
||||
// TODO: We're leaking shapes for long drawing sessions.
|
||||
@ -166,12 +180,16 @@ void Highlighter::UpdateDrawingPointPosition(MouseButton button)
|
||||
|
||||
if (button == MouseButton::Left)
|
||||
{
|
||||
m_leftPointer.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y )});
|
||||
m_leftPointer.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y) });
|
||||
}
|
||||
else if (button == MouseButton::Right)
|
||||
{
|
||||
m_rightPointer.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y) });
|
||||
}
|
||||
else
|
||||
{
|
||||
//right
|
||||
m_rightPointer.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y )});
|
||||
// always
|
||||
m_alwaysPointer.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y) });
|
||||
}
|
||||
}
|
||||
void Highlighter::StartDrawingPointFading(MouseButton button)
|
||||
@ -183,7 +201,7 @@ void Highlighter::StartDrawingPointFading(MouseButton button)
|
||||
}
|
||||
else
|
||||
{
|
||||
//right
|
||||
// right
|
||||
circleShape = m_rightPointer;
|
||||
}
|
||||
|
||||
@ -201,6 +219,15 @@ void Highlighter::StartDrawingPointFading(MouseButton button)
|
||||
circleShape.FillBrush().StartAnimation(L"Color", animation);
|
||||
}
|
||||
|
||||
void Highlighter::ClearDrawingPoint(MouseButton _button)
|
||||
{
|
||||
winrt::Windows::UI::Composition::CompositionSpriteShape circleShape{ nullptr };
|
||||
|
||||
// always
|
||||
circleShape = m_alwaysPointer;
|
||||
|
||||
circleShape.FillBrush().as<winrt::Windows::UI::Composition::CompositionColorBrush>().Color(winrt::Windows::UI::ColorHelper::FromArgb(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
void Highlighter::ClearDrawing()
|
||||
{
|
||||
@ -221,12 +248,28 @@ LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lPa
|
||||
switch (wParam)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
instance->AddDrawingPoint(MouseButton::Left);
|
||||
instance->m_leftButtonPressed = true;
|
||||
if (instance->m_leftPointerEnabled)
|
||||
{
|
||||
if (instance->m_alwaysPointerEnabled && !instance->m_rightButtonPressed)
|
||||
{
|
||||
// Clear AlwaysPointer only when it's enabled and RightPointer is not active
|
||||
instance->ClearDrawingPoint(MouseButton::None);
|
||||
}
|
||||
instance->AddDrawingPoint(MouseButton::Left);
|
||||
instance->m_leftButtonPressed = true;
|
||||
}
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
instance->AddDrawingPoint(MouseButton::Right);
|
||||
instance->m_rightButtonPressed = true;
|
||||
if (instance->m_rightPointerEnabled)
|
||||
{
|
||||
if (instance->m_alwaysPointerEnabled && !instance->m_leftButtonPressed)
|
||||
{
|
||||
// Clear AlwaysPointer only when it's enabled and LeftPointer is not active
|
||||
instance->ClearDrawingPoint(MouseButton::None);
|
||||
}
|
||||
instance->AddDrawingPoint(MouseButton::Right);
|
||||
instance->m_rightButtonPressed = true;
|
||||
}
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
if (instance->m_leftButtonPressed)
|
||||
@ -237,12 +280,21 @@ LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lPa
|
||||
{
|
||||
instance->UpdateDrawingPointPosition(MouseButton::Right);
|
||||
}
|
||||
if (instance->m_alwaysPointerEnabled && !instance->m_leftButtonPressed && !instance->m_rightButtonPressed)
|
||||
{
|
||||
instance->UpdateDrawingPointPosition(MouseButton::None);
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
if (instance->m_leftButtonPressed)
|
||||
{
|
||||
instance->StartDrawingPointFading(MouseButton::Left);
|
||||
instance->m_leftButtonPressed = false;
|
||||
if (instance->m_alwaysPointerEnabled && !instance->m_rightButtonPressed)
|
||||
{
|
||||
// Add AlwaysPointer only when it's enabled and RightPointer is not active
|
||||
instance->AddDrawingPoint(MouseButton::None);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
@ -250,6 +302,11 @@ LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lPa
|
||||
{
|
||||
instance->StartDrawingPointFading(MouseButton::Right);
|
||||
instance->m_rightButtonPressed = false;
|
||||
if (instance->m_alwaysPointerEnabled && !instance->m_leftButtonPressed)
|
||||
{
|
||||
// Add AlwaysPointer only when it's enabled and LeftPointer is not active
|
||||
instance->AddDrawingPoint(MouseButton::None);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -270,6 +327,7 @@ void Highlighter::StartDrawing()
|
||||
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN) + 1, GetSystemMetrics(SM_YVIRTUALSCREEN) + 1, GetSystemMetrics(SM_CXVIRTUALSCREEN) - 2, GetSystemMetrics(SM_CYVIRTUALSCREEN) - 2, 0);
|
||||
ClearDrawing();
|
||||
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
|
||||
instance->AddDrawingPoint(MouseButton::None);
|
||||
m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, m_hinstance, 0);
|
||||
}
|
||||
|
||||
@ -281,6 +339,7 @@ void Highlighter::StopDrawing()
|
||||
m_rightButtonPressed = false;
|
||||
m_leftPointer = nullptr;
|
||||
m_rightPointer = nullptr;
|
||||
m_alwaysPointer = nullptr;
|
||||
ShowWindow(m_hwnd, SW_HIDE);
|
||||
UnhookWindowsHookEx(m_mouseHook);
|
||||
ClearDrawing();
|
||||
@ -298,6 +357,10 @@ void Highlighter::ApplySettings(MouseHighlighterSettings settings) {
|
||||
m_fadeDuration_ms = settings.fadeDurationMs;
|
||||
m_leftClickColor = settings.leftButtonColor;
|
||||
m_rightClickColor = settings.rightButtonColor;
|
||||
m_alwaysColor = settings.alwaysColor;
|
||||
m_leftPointerEnabled = settings.leftButtonColor.A != 0;
|
||||
m_rightPointerEnabled = settings.rightButtonColor.A != 0;
|
||||
m_alwaysPointerEnabled = settings.alwaysColor.A != 0;
|
||||
}
|
||||
|
||||
void Highlighter::DestroyHighlighter()
|
||||
|
@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
#include "pch.h"
|
||||
|
||||
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_OPACITY = 65;
|
||||
const winrt::Windows::UI::Color MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(MOUSE_HIGHLIGHTER_DEFAULT_OPACITY, 255, 255, 0);
|
||||
const winrt::Windows::UI::Color MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(MOUSE_HIGHLIGHTER_DEFAULT_OPACITY, 0, 0, 255);
|
||||
const winrt::Windows::UI::Color MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(166, 255, 255, 0);
|
||||
const winrt::Windows::UI::Color MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(166, 0, 0, 255);
|
||||
const winrt::Windows::UI::Color MOUSE_HIGHLIGHTER_DEFAULT_ALWAYS_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(0, 255, 0, 0);
|
||||
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_RADIUS = 20;
|
||||
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_DELAY_MS = 500;
|
||||
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_DURATION_MS = 250;
|
||||
@ -12,6 +12,7 @@ struct MouseHighlighterSettings
|
||||
{
|
||||
winrt::Windows::UI::Color leftButtonColor = MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR;
|
||||
winrt::Windows::UI::Color rightButtonColor = MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR;
|
||||
winrt::Windows::UI::Color alwaysColor = MOUSE_HIGHLIGHTER_DEFAULT_ALWAYS_COLOR;
|
||||
int radius = MOUSE_HIGHLIGHTER_DEFAULT_RADIUS;
|
||||
int fadeDelayMs = MOUSE_HIGHLIGHTER_DEFAULT_DELAY_MS;
|
||||
int fadeDurationMs = MOUSE_HIGHLIGHTER_DEFAULT_DURATION_MS;
|
||||
|
@ -13,6 +13,7 @@ namespace
|
||||
const wchar_t JSON_KEY_LEFT_BUTTON_CLICK_COLOR[] = L"left_button_click_color";
|
||||
const wchar_t JSON_KEY_RIGHT_BUTTON_CLICK_COLOR[] = L"right_button_click_color";
|
||||
const wchar_t JSON_KEY_HIGHLIGHT_OPACITY[] = L"highlight_opacity";
|
||||
const wchar_t JSON_KEY_ALWAYS_COLOR[] = L"always_color";
|
||||
const wchar_t JSON_KEY_HIGHLIGHT_RADIUS[] = L"highlight_radius";
|
||||
const wchar_t JSON_KEY_HIGHLIGHT_FADE_DELAY_MS[] = L"highlight_fade_delay_ms";
|
||||
const wchar_t JSON_KEY_HIGHLIGHT_FADE_DURATION_MS[] = L"highlight_fade_duration_ms";
|
||||
@ -210,45 +211,53 @@ public:
|
||||
{
|
||||
Logger::warn("Failed to initialize Mouse Highlighter activation shortcut");
|
||||
}
|
||||
uint8_t opacity = MOUSE_HIGHLIGHTER_DEFAULT_OPACITY;
|
||||
try
|
||||
// Migration from <=1.1
|
||||
auto version = (std::wstring)settingsObject.GetNamedString(L"version");
|
||||
auto migration = false;
|
||||
uint8_t opacity = 166;
|
||||
if (version == L"1.0" || version == L"1.1")
|
||||
{
|
||||
// Parse Opacity
|
||||
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_OPACITY);
|
||||
int value = static_cast<int>(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
|
||||
if (value >= 0)
|
||||
migration = true;
|
||||
try
|
||||
{
|
||||
opacity = value;
|
||||
// Parse Opacity
|
||||
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_OPACITY);
|
||||
int value = static_cast<int>(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
|
||||
if (value >= 0)
|
||||
{
|
||||
if (version == L"1.0")
|
||||
{
|
||||
opacity = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1.1
|
||||
opacity = value * 255 / 100;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (...)
|
||||
{
|
||||
throw;
|
||||
Logger::warn("Failed to initialize Opacity from settings. Will use default value");
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::warn("Failed to initialize Opacity from settings. Will use default value");
|
||||
}
|
||||
|
||||
// Convert % to uint8_t
|
||||
if ((std::wstring)settingsObject.GetNamedString(L"version") != L"1.0")
|
||||
{
|
||||
opacity = opacity * 255 / 100;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Parse left button click color
|
||||
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_LEFT_BUTTON_CLICK_COLOR);
|
||||
auto leftColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
|
||||
uint8_t r, g, b;
|
||||
if (!checkValidRGB(leftColor, &r, &g, &b))
|
||||
uint8_t a = opacity, r, g, b;
|
||||
if (!migration && !checkValidARGB(leftColor, &a, &r, &g, &b) || migration && !checkValidRGB(leftColor, &r, &g, &b))
|
||||
{
|
||||
Logger::error("Left click color RGB value is invalid. Will use default value");
|
||||
Logger::error("Left click color ARGB value is invalid. Will use default value");
|
||||
}
|
||||
else
|
||||
{
|
||||
highlightSettings.leftButtonColor = winrt::Windows::UI::ColorHelper::FromArgb(opacity, r, g, b);
|
||||
highlightSettings.leftButtonColor = winrt::Windows::UI::ColorHelper::FromArgb(a, r, g, b);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@ -260,14 +269,14 @@ public:
|
||||
// Parse right button click color
|
||||
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_RIGHT_BUTTON_CLICK_COLOR);
|
||||
auto rightColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
|
||||
uint8_t r, g, b;
|
||||
if (!checkValidRGB(rightColor, &r, &g, &b))
|
||||
uint8_t a = opacity, r, g, b;
|
||||
if (!migration && !checkValidARGB(rightColor, &a, &r, &g, &b) || migration && !checkValidRGB(rightColor, &r, &g, &b))
|
||||
{
|
||||
Logger::error("Right click color RGB value is invalid. Will use default value");
|
||||
Logger::error("Right click color ARGB value is invalid. Will use default value");
|
||||
}
|
||||
else
|
||||
{
|
||||
highlightSettings.rightButtonColor = winrt::Windows::UI::ColorHelper::FromArgb(opacity, r, g, b);
|
||||
highlightSettings.rightButtonColor = winrt::Windows::UI::ColorHelper::FromArgb(a, r, g, b);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@ -275,6 +284,25 @@ public:
|
||||
Logger::warn("Failed to initialize right click color from settings. Will use default value");
|
||||
}
|
||||
try
|
||||
{
|
||||
// Parse always color
|
||||
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ALWAYS_COLOR);
|
||||
auto alwaysColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
|
||||
uint8_t a, r, g, b;
|
||||
if (!migration && !checkValidARGB(alwaysColor, &a, &r, &g, &b))
|
||||
{
|
||||
Logger::error("Always color ARGB value is invalid. Will use default value");
|
||||
}
|
||||
else
|
||||
{
|
||||
highlightSettings.alwaysColor = winrt::Windows::UI::ColorHelper::FromArgb(a, r, g, b);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::warn("Failed to initialize always color from settings. Will use default value");
|
||||
}
|
||||
try
|
||||
{
|
||||
// Parse Radius
|
||||
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_RADIUS);
|
||||
|
@ -35,5 +35,33 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
|
||||
return "#FFFFFF";
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToARGBHex(string color)
|
||||
{
|
||||
if (color == null)
|
||||
{
|
||||
return "#FFFFFFFF";
|
||||
}
|
||||
|
||||
// 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.A.ToString("X2", CultureInfo.InvariantCulture) +
|
||||
clr.R.ToString("X2", CultureInfo.InvariantCulture) +
|
||||
clr.G.ToString("X2", CultureInfo.InvariantCulture) +
|
||||
clr.B.ToString("X2", CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "#FFFFFFFF";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
[JsonPropertyName("highlight_opacity")]
|
||||
public IntProperty HighlightOpacity { get; set; }
|
||||
|
||||
[JsonPropertyName("always_color")]
|
||||
public StringProperty AlwaysColor { get; set; }
|
||||
|
||||
[JsonPropertyName("highlight_radius")]
|
||||
public IntProperty HighlightRadius { get; set; }
|
||||
|
||||
@ -34,9 +37,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
public MouseHighlighterProperties()
|
||||
{
|
||||
ActivationShortcut = DefaultActivationShortcut;
|
||||
LeftButtonClickColor = new StringProperty("#FFFF00");
|
||||
RightButtonClickColor = new StringProperty("#0000FF");
|
||||
HighlightOpacity = new IntProperty(65);
|
||||
LeftButtonClickColor = new StringProperty("#a6FFFF00");
|
||||
RightButtonClickColor = new StringProperty("#a60000FF");
|
||||
AlwaysColor = new StringProperty("#00FF0000");
|
||||
HighlightOpacity = new IntProperty(166); // for migration from <=1.1 to 1.2
|
||||
HighlightRadius = new IntProperty(20);
|
||||
HighlightFadeDelayMs = new IntProperty(500);
|
||||
HighlightFadeDurationMs = new IntProperty(250);
|
||||
|
@ -2,6 +2,8 @@
|
||||
// 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.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
@ -18,7 +20,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
Name = ModuleName;
|
||||
Properties = new MouseHighlighterProperties();
|
||||
Version = "1.1";
|
||||
Version = "1.2";
|
||||
}
|
||||
|
||||
public string GetModuleName()
|
||||
@ -29,11 +31,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
// This can be utilized in the future if the settings.json file is to be modified/deleted.
|
||||
public bool UpgradeSettingsConfiguration()
|
||||
{
|
||||
// Migrate settings from 1.0 to 1.1
|
||||
if (Version == "1.0")
|
||||
if (Version == "1.0" || Version == "1.1")
|
||||
{
|
||||
Version = "1.1";
|
||||
Properties.HighlightOpacity = new IntProperty(Properties.HighlightOpacity.Value * 100 / 255);
|
||||
string opacity;
|
||||
if (Version == "1.0")
|
||||
{
|
||||
opacity = string.Format(CultureInfo.InvariantCulture, "{0:X2}", Properties.HighlightOpacity.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1.1
|
||||
opacity = string.Format(CultureInfo.InvariantCulture, "{0:X2}", Properties.HighlightOpacity.Value * 255 / 100);
|
||||
}
|
||||
|
||||
Properties.LeftButtonClickColor = new StringProperty(string.Concat("#", opacity, Properties.LeftButtonClickColor.Value.ToString().Substring(1, 6)));
|
||||
Properties.RightButtonClickColor = new StringProperty(string.Concat("#", opacity, Properties.RightButtonClickColor.Value.ToString().Substring(1, 6)));
|
||||
Version = "1.2";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,42 @@
|
||||
<UserControl
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.Controls.AlphaColorPickerButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<!--TODO(stefan): ToDisplayName is no longer available in ColorHelper
|
||||
<DropDownButton Padding="4,4,8,4" AutomationProperties.FullDescription="{x:Bind clr:ColorHelper.ToDisplayName(SelectedColor), Mode=OneWay }">
|
||||
-->
|
||||
<DropDownButton Padding="4,4,8,4">
|
||||
<Border
|
||||
x:Name="ColorPreviewBorder"
|
||||
Width="48"
|
||||
Height="24"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{ThemeResource ControlCornerRadius}">
|
||||
<Border.Background>
|
||||
<SolidColorBrush Color="{x:Bind SelectedColor, Mode=OneWay}" />
|
||||
</Border.Background>
|
||||
</Border>
|
||||
<DropDownButton.Flyout>
|
||||
<Flyout>
|
||||
<ColorPicker
|
||||
IsAlphaEnabled="True"
|
||||
IsAlphaSliderVisible="True"
|
||||
IsAlphaTextInputVisible="True"
|
||||
IsColorChannelTextInputVisible="True"
|
||||
IsColorSliderVisible="True"
|
||||
IsHexInputVisible="True"
|
||||
Color="{x:Bind SelectedColor, Mode=TwoWay}" />
|
||||
</Flyout>
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
</Grid>
|
||||
</UserControl>
|
@ -0,0 +1,59 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -163,17 +163,13 @@
|
||||
IsEnabled="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=OneWay}">
|
||||
<labs:SettingsExpander.Items>
|
||||
<labs:SettingsCard x:Uid="MouseUtils_MouseHighlighter_PrimaryButtonClickColor">
|
||||
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterLeftButtonClickColor, Mode=TwoWay}" />
|
||||
<controls:AlphaColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterLeftButtonClickColor, Mode=TwoWay}" />
|
||||
</labs:SettingsCard>
|
||||
<labs:SettingsCard x:Uid="MouseUtils_MouseHighlighter_SecondaryButtonClickColor">
|
||||
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterRightButtonClickColor, Mode=TwoWay}" />
|
||||
<controls:AlphaColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterRightButtonClickColor, Mode=TwoWay}" />
|
||||
</labs:SettingsCard>
|
||||
<labs:SettingsCard x:Uid="MouseUtils_MouseHighlighter_HighlightOpacity">
|
||||
<Slider
|
||||
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||
Maximum="100"
|
||||
Minimum="1"
|
||||
Value="{x:Bind Mode=TwoWay, Path=ViewModel.MouseHighlighterOpacity}" />
|
||||
<labs:SettingsCard x:Uid="MouseUtils_MouseHighlighter_AlwaysColor">
|
||||
<controls:AlphaColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterAlwaysColor, Mode=TwoWay}" />
|
||||
</labs:SettingsCard>
|
||||
<labs:SettingsCard x:Uid="MouseUtils_MouseHighlighter_HighlightRadius">
|
||||
<NumberBox
|
||||
|
@ -2601,9 +2601,6 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<data name="MouseUtils_MouseHighlighter_SecondaryButtonClickColor.Header" xml:space="preserve">
|
||||
<value>Secondary button highlight color</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseHighlighter_HighlightOpacity.Header" xml:space="preserve">
|
||||
<value>Opacity (%)</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseHighlighter_HighlightRadius.Header" xml:space="preserve">
|
||||
<value>Radius (px)</value>
|
||||
<comment>px = pixels</comment>
|
||||
@ -3590,6 +3587,9 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="Hosts_Encoding_Utf8Bom.Content" xml:space="preserve">
|
||||
<value>UTF-8 with BOM</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseHighlighter_AlwaysColor.Header" xml:space="preserve">
|
||||
<value>Always highlight color</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MousePointerCrosshairs_CrosshairsAutoHide.Content" xml:space="preserve">
|
||||
<value>Automatically hide crosshairs when the mouse pointer is hidden</value>
|
||||
</data>
|
||||
|
@ -71,12 +71,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
MouseHighlighterSettingsConfig = mouseHighlighterSettingsRepository.SettingsConfig;
|
||||
string leftClickColor = MouseHighlighterSettingsConfig.Properties.LeftButtonClickColor.Value;
|
||||
_highlighterLeftButtonClickColor = !string.IsNullOrEmpty(leftClickColor) ? leftClickColor : "#FFFF00";
|
||||
_highlighterLeftButtonClickColor = !string.IsNullOrEmpty(leftClickColor) ? leftClickColor : "#a6FFFF00";
|
||||
|
||||
string rightClickColor = MouseHighlighterSettingsConfig.Properties.RightButtonClickColor.Value;
|
||||
_highlighterRightButtonClickColor = !string.IsNullOrEmpty(rightClickColor) ? rightClickColor : "#0000FF";
|
||||
_highlighterRightButtonClickColor = !string.IsNullOrEmpty(rightClickColor) ? rightClickColor : "#a60000FF";
|
||||
|
||||
string alwaysColor = MouseHighlighterSettingsConfig.Properties.AlwaysColor.Value;
|
||||
_highlighterAlwaysColor = !string.IsNullOrEmpty(alwaysColor) ? alwaysColor : "#00FF0000";
|
||||
|
||||
_highlighterOpacity = MouseHighlighterSettingsConfig.Properties.HighlightOpacity.Value;
|
||||
_highlighterRadius = MouseHighlighterSettingsConfig.Properties.HighlightRadius.Value;
|
||||
_highlightFadeDelayMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDelayMs.Value;
|
||||
_highlightFadeDurationMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDurationMs.Value;
|
||||
@ -445,7 +447,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
set
|
||||
{
|
||||
value = SettingsUtilities.ToRGBHex(value);
|
||||
value = SettingsUtilities.ToARGBHex(value);
|
||||
if (!value.Equals(_highlighterLeftButtonClickColor, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_highlighterLeftButtonClickColor = value;
|
||||
@ -464,7 +466,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
set
|
||||
{
|
||||
value = SettingsUtilities.ToRGBHex(value);
|
||||
value = SettingsUtilities.ToARGBHex(value);
|
||||
if (!value.Equals(_highlighterRightButtonClickColor, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_highlighterRightButtonClickColor = value;
|
||||
@ -474,19 +476,20 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public int MouseHighlighterOpacity
|
||||
public string MouseHighlighterAlwaysColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return _highlighterOpacity;
|
||||
return _highlighterAlwaysColor;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value != _highlighterOpacity)
|
||||
value = SettingsUtilities.ToARGBHex(value);
|
||||
if (!value.Equals(_highlighterAlwaysColor, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_highlighterOpacity = value;
|
||||
MouseHighlighterSettingsConfig.Properties.HighlightOpacity.Value = value;
|
||||
_highlighterAlwaysColor = value;
|
||||
MouseHighlighterSettingsConfig.Properties.AlwaysColor.Value = value;
|
||||
NotifyMouseHighlighterPropertyChanged();
|
||||
}
|
||||
}
|
||||
@ -889,7 +892,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
private bool _isMouseHighlighterEnabled;
|
||||
private string _highlighterLeftButtonClickColor;
|
||||
private string _highlighterRightButtonClickColor;
|
||||
private int _highlighterOpacity;
|
||||
private string _highlighterAlwaysColor;
|
||||
private int _highlighterRadius;
|
||||
private int _highlightFadeDelayMs;
|
||||
private int _highlightFadeDurationMs;
|
||||
|
Loading…
Reference in New Issue
Block a user