Compare commits

...

3 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
14820a22a4 Complete UI settings for Mouse Highlighter mode switch shortcut
Co-authored-by: vanzue <69313318+vanzue@users.noreply.github.com>
2025-09-04 01:19:58 +00:00
copilot-swe-agent[bot]
b6e002c565 Add mode switch shortcut for Mouse Highlighter
Co-authored-by: vanzue <69313318+vanzue@users.noreply.github.com>
2025-09-04 01:16:21 +00:00
copilot-swe-agent[bot]
ba4c57ed2e Initial plan 2025-09-04 01:00:20 +00:00
7 changed files with 158 additions and 34 deletions

View File

@@ -27,6 +27,7 @@ struct Highlighter
static Highlighter* instance; static Highlighter* instance;
void Terminate(); void Terminate();
void SwitchActivationMode(); void SwitchActivationMode();
void SwitchHighlightMode();
void ApplySettings(MouseHighlighterSettings settings); void ApplySettings(MouseHighlighterSettings settings);
private: private:
@@ -60,6 +61,7 @@ private:
HWND m_hwnd = NULL; HWND m_hwnd = NULL;
HINSTANCE m_hinstance = NULL; HINSTANCE m_hinstance = NULL;
static constexpr DWORD WM_SWITCH_ACTIVATION_MODE = WM_APP; static constexpr DWORD WM_SWITCH_ACTIVATION_MODE = WM_APP;
static constexpr DWORD WM_SWITCH_HIGHLIGHT_MODE = WM_APP + 1;
winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr }; winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
winrt::Compositor m_compositor{ nullptr }; winrt::Compositor m_compositor{ nullptr };
@@ -466,6 +468,11 @@ void Highlighter::SwitchActivationMode()
PostMessage(m_hwnd, WM_SWITCH_ACTIVATION_MODE, 0, 0); PostMessage(m_hwnd, WM_SWITCH_ACTIVATION_MODE, 0, 0);
} }
void Highlighter::SwitchHighlightMode()
{
PostMessage(m_hwnd, WM_SWITCH_HIGHLIGHT_MODE, 0, 0);
}
void Highlighter::ApplySettings(MouseHighlighterSettings settings) void Highlighter::ApplySettings(MouseHighlighterSettings settings)
{ {
m_radius = static_cast<float>(settings.radius); m_radius = static_cast<float>(settings.radius);
@@ -535,6 +542,15 @@ LRESULT CALLBACK Highlighter::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP
instance->StartDrawing(); instance->StartDrawing();
} }
break; break;
case WM_SWITCH_HIGHLIGHT_MODE:
// Toggle spotlight mode
instance->m_spotlightMode = !instance->m_spotlightMode;
if (instance->m_visible)
{
instance->StopDrawing();
instance->StartDrawing();
}
break;
case WM_DESTROY: case WM_DESTROY:
instance->DestroyHighlighter(); instance->DestroyHighlighter();
break; break;
@@ -663,6 +679,15 @@ void MouseHighlighterSwitch()
} }
} }
void MouseHighlighterSwitchMode()
{
if (Highlighter::instance != nullptr)
{
Logger::info("Switching highlight mode.");
Highlighter::instance->SwitchHighlightMode();
}
}
void MouseHighlighterDisable() void MouseHighlighterDisable()
{ {
if (Highlighter::instance != nullptr) if (Highlighter::instance != nullptr)

View File

@@ -25,4 +25,5 @@ int MouseHighlighterMain(HINSTANCE hinst, MouseHighlighterSettings settings);
void MouseHighlighterDisable(); void MouseHighlighterDisable();
bool MouseHighlighterIsEnabled(); bool MouseHighlighterIsEnabled();
void MouseHighlighterSwitch(); void MouseHighlighterSwitch();
void MouseHighlighterSwitchMode();
void MouseHighlighterApplySettings(MouseHighlighterSettings settings); void MouseHighlighterApplySettings(MouseHighlighterSettings settings);

View File

@@ -4,12 +4,15 @@
#include "trace.h" #include "trace.h"
#include "MouseHighlighter.h" #include "MouseHighlighter.h"
#include "common/utils/color.h" #include "common/utils/color.h"
#include <algorithm>
#include <vector>
namespace namespace
{ {
const wchar_t JSON_KEY_PROPERTIES[] = L"properties"; const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
const wchar_t JSON_KEY_VALUE[] = L"value"; const wchar_t JSON_KEY_VALUE[] = L"value";
const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"activation_shortcut"; const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"activation_shortcut";
const wchar_t JSON_KEY_MODE_SWITCH_SHORTCUT[] = L"mode_switch_shortcut";
const wchar_t JSON_KEY_LEFT_BUTTON_CLICK_COLOR[] = L"left_button_click_color"; 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_RIGHT_BUTTON_CLICK_COLOR[] = L"right_button_click_color";
const wchar_t JSON_KEY_HIGHLIGHT_OPACITY[] = L"highlight_opacity"; const wchar_t JSON_KEY_HIGHLIGHT_OPACITY[] = L"highlight_opacity";
@@ -55,8 +58,8 @@ private:
// The PowerToy state. // The PowerToy state.
bool m_enabled = false; bool m_enabled = false;
// Hotkey to invoke the module // Hotkeys to invoke the module
HotkeyEx m_hotkey; std::vector<PowertoyModuleIface::Hotkey> m_hotkeys;
// Mouse Highlighter specific settings // Mouse Highlighter specific settings
MouseHighlighterSettings m_highlightSettings; MouseHighlighterSettings m_highlightSettings;
@@ -148,14 +151,29 @@ public:
return m_enabled; return m_enabled;
} }
virtual std::optional<HotkeyEx> GetHotkeyEx() override virtual size_t get_hotkeys(Hotkey* buffer, size_t buffer_size) override
{ {
return m_hotkey; if (buffer == nullptr || buffer_size == 0)
{
return m_hotkeys.size();
}
size_t copied = std::min(buffer_size, m_hotkeys.size());
std::copy_n(m_hotkeys.begin(), copied, buffer);
return copied;
} }
virtual void OnHotkeyEx() override virtual bool on_hotkey(size_t hotkeyId) override
{ {
MouseHighlighterSwitch(); if (hotkeyId == 0)
{
MouseHighlighterSwitch();
}
else if (hotkeyId == 1)
{
MouseHighlighterSwitchMode();
}
return true;
} }
// Load the settings file. // Load the settings file.
@@ -183,36 +201,43 @@ public:
{ {
try try
{ {
// Parse HotKey // Initialize hotkeys vector
m_hotkeys.clear();
m_hotkeys.resize(2); // Activation and Mode Switch hotkeys
// Parse Activation HotKey
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ACTIVATION_SHORTCUT); auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ACTIVATION_SHORTCUT);
auto hotkey = PowerToysSettings::HotkeyObject::from_json(jsonPropertiesObject); auto hotkey = PowerToysSettings::HotkeyObject::from_json(jsonPropertiesObject);
m_hotkey = HotkeyEx();
if (hotkey.win_pressed()) m_hotkeys[0].win = hotkey.win_pressed();
{ m_hotkeys[0].ctrl = hotkey.ctrl_pressed();
m_hotkey.modifiersMask |= MOD_WIN; m_hotkeys[0].shift = hotkey.shift_pressed();
} m_hotkeys[0].alt = hotkey.alt_pressed();
m_hotkeys[0].key = hotkey.get_code();
if (hotkey.ctrl_pressed()) m_hotkeys[0].id = 0;
{
m_hotkey.modifiersMask |= MOD_CONTROL;
}
if (hotkey.shift_pressed())
{
m_hotkey.modifiersMask |= MOD_SHIFT;
}
if (hotkey.alt_pressed())
{
m_hotkey.modifiersMask |= MOD_ALT;
}
m_hotkey.vkCode = hotkey.get_code();
} }
catch (...) catch (...)
{ {
Logger::warn("Failed to initialize Mouse Highlighter activation shortcut"); Logger::warn("Failed to initialize Mouse Highlighter activation shortcut");
} }
try
{
// Parse Mode Switch HotKey
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_MODE_SWITCH_SHORTCUT);
auto hotkey = PowerToysSettings::HotkeyObject::from_json(jsonPropertiesObject);
m_hotkeys[1].win = hotkey.win_pressed();
m_hotkeys[1].ctrl = hotkey.ctrl_pressed();
m_hotkeys[1].shift = hotkey.shift_pressed();
m_hotkeys[1].alt = hotkey.alt_pressed();
m_hotkeys[1].key = hotkey.get_code();
m_hotkeys[1].id = 1;
}
catch (...)
{
Logger::warn("Failed to initialize Mouse Highlighter mode switch shortcut");
}
// Migration from <=1.1 // Migration from <=1.1
auto version = (std::wstring)settingsObject.GetNamedString(L"version"); auto version = (std::wstring)settingsObject.GetNamedString(L"version");
auto migration = false; auto migration = false;
@@ -383,12 +408,47 @@ public:
{ {
Logger::info("Mouse Highlighter settings are empty"); Logger::info("Mouse Highlighter settings are empty");
} }
if (!m_hotkey.modifiersMask)
// Set default hotkeys if not configured
if (m_hotkeys.empty() || m_hotkeys.size() < 2)
{ {
Logger::info("Mouse Highlighter is going to use default shortcut"); Logger::info("Mouse Highlighter is going to use default shortcuts");
m_hotkey.modifiersMask = MOD_SHIFT | MOD_WIN; m_hotkeys.clear();
m_hotkey.vkCode = 0x48; // H key m_hotkeys.resize(2);
// Default activation shortcut: Win + Shift + H
m_hotkeys[0].win = true;
m_hotkeys[0].shift = true;
m_hotkeys[0].key = 0x48; // H key
m_hotkeys[0].id = 0;
// Default mode switch shortcut: Win + Shift + M
m_hotkeys[1].win = true;
m_hotkeys[1].shift = true;
m_hotkeys[1].key = 0x4D; // M key
m_hotkeys[1].id = 1;
} }
else
{
// Check if activation hotkey is empty and set default
if (!m_hotkeys[0].win && !m_hotkeys[0].ctrl && !m_hotkeys[0].shift && !m_hotkeys[0].alt && m_hotkeys[0].key == 0)
{
m_hotkeys[0].win = true;
m_hotkeys[0].shift = true;
m_hotkeys[0].key = 0x48; // H key
m_hotkeys[0].id = 0;
}
// Check if mode switch hotkey is empty and set default
if (!m_hotkeys[1].win && !m_hotkeys[1].ctrl && !m_hotkeys[1].shift && !m_hotkeys[1].alt && m_hotkeys[1].key == 0)
{
m_hotkeys[1].win = true;
m_hotkeys[1].shift = true;
m_hotkeys[1].key = 0x4D; // M key
m_hotkeys[1].id = 1;
}
}
m_highlightSettings = highlightSettings; m_highlightSettings = highlightSettings;
} }
}; };

View File

@@ -44,6 +44,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("spotlight_mode")] [JsonPropertyName("spotlight_mode")]
public BoolProperty SpotlightMode { get; set; } public BoolProperty SpotlightMode { get; set; }
[JsonPropertyName("mode_switch_shortcut")]
public HotkeySettings ModeSwitchShortcut { get; set; }
[CmdConfigureIgnore]
public HotkeySettings DefaultModeSwitchShortcut => new HotkeySettings(true, false, false, true, 0x4D);
public MouseHighlighterProperties() public MouseHighlighterProperties()
{ {
ActivationShortcut = DefaultActivationShortcut; ActivationShortcut = DefaultActivationShortcut;
@@ -56,6 +62,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
HighlightFadeDurationMs = new IntProperty(250); HighlightFadeDurationMs = new IntProperty(250);
AutoActivate = new BoolProperty(false); AutoActivate = new BoolProperty(false);
SpotlightMode = new BoolProperty(false); SpotlightMode = new BoolProperty(false);
ModeSwitchShortcut = DefaultModeSwitchShortcut;
} }
} }
} }

View File

@@ -226,6 +226,13 @@
</tkcontrols:SettingsCard> </tkcontrols:SettingsCard>
</tkcontrols:SettingsExpander.Items> </tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander> </tkcontrols:SettingsExpander>
<tkcontrols:SettingsCard
Name="MouseUtilsMouseHighlighterModeSwitchShortcut"
x:Uid="MouseUtils_MouseHighlighter_ModeSwitchShortcut"
HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}"
IsEnabled="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=OneWay}">
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}" HotkeySettings="{x:Bind Path=ViewModel.MouseHighlighterModeSwitchShortcut, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsExpander <tkcontrols:SettingsExpander
Name="MouseHighlighterAppearanceBehavior" Name="MouseHighlighterAppearanceBehavior"
x:Uid="Appearance_Behavior" x:Uid="Appearance_Behavior"

View File

@@ -2824,6 +2824,13 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
<value>Customize the shortcut to turn on or off this mode</value> <value>Customize the shortcut to turn on or off this mode</value>
<comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment> <comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment>
</data> </data>
<data name="MouseUtils_MouseHighlighter_ModeSwitchShortcut.Header" xml:space="preserve">
<value>Mode switch shortcut</value>
</data>
<data name="MouseUtils_MouseHighlighter_ModeSwitchShortcut.Description" xml:space="preserve">
<value>Customize the shortcut to switch between spotlight and circle highlight modes</value>
<comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment>
</data>
<data name="MouseUtils_MouseHighlighter_PrimaryButtonClickColor.Header" xml:space="preserve"> <data name="MouseUtils_MouseHighlighter_PrimaryButtonClickColor.Header" xml:space="preserve">
<value>Primary button highlight color</value> <value>Primary button highlight color</value>
</data> </data>

View File

@@ -158,7 +158,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
var hotkeysDict = new Dictionary<string, HotkeySettings[]> var hotkeysDict = new Dictionary<string, HotkeySettings[]>
{ {
[FindMyMouseSettings.ModuleName] = [FindMyMouseActivationShortcut], [FindMyMouseSettings.ModuleName] = [FindMyMouseActivationShortcut],
[MouseHighlighterSettings.ModuleName] = [MouseHighlighterActivationShortcut], [MouseHighlighterSettings.ModuleName] = [MouseHighlighterActivationShortcut, MouseHighlighterModeSwitchShortcut],
[MousePointerCrosshairsSettings.ModuleName] = [ [MousePointerCrosshairsSettings.ModuleName] = [
MousePointerCrosshairsActivationShortcut, MousePointerCrosshairsActivationShortcut,
GlidingCursorActivationShortcut], GlidingCursorActivationShortcut],
@@ -523,6 +523,23 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
} }
} }
public HotkeySettings MouseHighlighterModeSwitchShortcut
{
get
{
return MouseHighlighterSettingsConfig.Properties.ModeSwitchShortcut;
}
set
{
if (MouseHighlighterSettingsConfig.Properties.ModeSwitchShortcut != value)
{
MouseHighlighterSettingsConfig.Properties.ModeSwitchShortcut = value ?? MouseHighlighterSettingsConfig.Properties.DefaultModeSwitchShortcut;
NotifyMouseHighlighterPropertyChanged();
}
}
}
public string MouseHighlighterLeftButtonClickColor public string MouseHighlighterLeftButtonClickColor
{ {
get get