Skip to content

feat: add global hotkey to toggle refresh rate#17

Open
SilasSch wants to merge 2 commits into
masterfrom
feat/hotkey-toggle
Open

feat: add global hotkey to toggle refresh rate#17
SilasSch wants to merge 2 commits into
masterfrom
feat/hotkey-toggle

Conversation

@SilasSch
Copy link
Copy Markdown
Owner

  • Add HotkeyManager class using RegisterHotKey/UnregisterHotKey Win32 API
  • Add configurable hotkey in config.json (default: Ctrl+Shift+R)
  • Add hotkey menu item in tray context menu
  • Add hotkey configuration dialog with modifier checkboxes and key picker
  • Register/Unregister hotkey on startup/dispose

Closes #3

- Add HotkeyManager class using RegisterHotKey/UnregisterHotKey Win32 API
- Add configurable hotkey in config.json (default: Ctrl+Shift+R)
- Add hotkey menu item in tray context menu
- Add hotkey configuration dialog with modifier checkboxes and key picker
- Register/Unregister hotkey on startup/dispose

Closes #3
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a global, configurable hotkey to toggle the refresh rate from anywhere (using Win32 RegisterHotKey), integrating it into the tray menu and persisting settings in config.json (Issue #3).

Changes:

  • Introduces HotkeyManager to register/unregister a global hotkey and raise a managed event on WM_HOTKEY.
  • Adds hotkey settings (HotkeyModifiers, HotkeyKey) to AppConfig with defaults.
  • Extends the tray context menu with a Hotkey item and a configuration dialog; registers the hotkey on startup and disposes it on exit.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 9 comments.

File Description
TrayApp.cs Wires up global hotkey registration, tray menu item, and a dialog to configure/save the hotkey.
HotkeyManager.cs Implements Win32 hotkey registration and config parsing/display helpers.
Config.cs Adds persisted hotkey configuration fields with defaults.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread TrayApp.cs
Comment on lines +521 to +532
var keyLabel = new Label
{
AutoSize = true,
Text = "Key:",
Left = 12,
Top = 100
};

var keyCombo = new ComboBox
{
Left = 50,
Top = 97,
Comment thread HotkeyManager.cs Outdated
Comment on lines +30 to +35
if (!RegisterHotKey(_window.Handle, HOTKEY_ID, (uint)modifiers, (uint)key))
{
var errorCode = Marshal.GetLastWin32Error();
error = $"RegisterHotKey failed (error {errorCode}). The combination may be in use by another application.";
return false;
}
Comment thread HotkeyManager.cs Outdated
Comment on lines +88 to +95
modifiers |= part.ToLowerInvariant() switch
{
"ctrl" or "control" => ModifierKeys.Control,
"alt" => ModifierKeys.Alt,
"shift" => ModifierKeys.Shift,
"win" or "windows" => ModifierKeys.Windows,
_ => throw new ArgumentException($"Unknown modifier: {part}")
};
Comment thread TrayApp.cs Outdated
var instructionLabel = new Label
{
AutoSize = true,
Text = "Press the desired key combination:",
Comment thread TrayApp.cs
Comment on lines +626 to +634
var modifiers = ModifierKeys.None;
if (ctrlCheckBox.Checked) modifiers |= ModifierKeys.Control;
if (altCheckBox.Checked) modifiers |= ModifierKeys.Alt;
if (shiftCheckBox.Checked) modifiers |= ModifierKeys.Shift;

if (modifiers == 0)
{
return null;
}
Comment thread HotkeyManager.cs Outdated
return false;
}

// Strip modifier flags that may be part of the Keys enum value (e.g. "D" vs "D1")
Comment thread Config.cs
Comment on lines +10 to +11
public string HotkeyModifiers { get; set; } = "Ctrl+Shift";
public string HotkeyKey { get; set; } = "R";
Comment thread TrayApp.cs Outdated
Comment on lines +401 to +405
_hotkeyManager.TryRegister(ModifierKeys.Control | ModifierKeys.Shift, Keys.R, out _);
return;
}

_hotkeyManager.TryRegister(modifiers, key, out _);
Comment thread TrayApp.cs
Comment on lines +397 to +403
if (!HotkeyManager.TryParse(_config.HotkeyModifiers, _config.HotkeyKey,
out var modifiers, out var key, out var error))
{
// Fall back to Ctrl+Shift+R if config is invalid.
_hotkeyManager.TryRegister(ModifierKeys.Control | ModifierKeys.Shift, Keys.R, out _);
return;
}
- HotkeyManager: make TryParse non-throwing (returns false instead of ArgumentException)
- HotkeyManager: add MOD_NOREPEAT flag to prevent rapid repeat on hold
- HotkeyManager: fix misleading comment about modifier flag stripping
- Config.cs: normalize null/empty HotkeyModifiers/HotkeyKey in Load()
- TrayApp: add Win modifier checkbox in hotkey dialog
- TrayApp: fix dialog instruction text ('Press' → 'Select')
- TrayApp: surface registration error to user on startup
- TrayApp: reset invalid hotkey config to defaults instead of keeping broken values
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a configurable global hotkey (via Win32 RegisterHotKey) to toggle refresh rate from anywhere, integrating it into the tray menu and persisting it in config.json.

Changes:

  • Introduce HotkeyManager to register/unregister a global hotkey and raise a HotkeyPressed event.
  • Extend AppConfig to persist hotkey modifiers/key with defaults (Ctrl+Shift+R).
  • Add tray UI for showing/configuring the hotkey, plus a small configuration dialog.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
TrayApp.cs Wires up global hotkey registration, adds tray menu entry + configuration dialog, triggers toggle on hotkey press.
HotkeyManager.cs New Win32-backed manager for registering/unregistering and dispatching WM_HOTKEY to managed events.
Config.cs Adds hotkey fields to config and normalizes missing/blank values on load.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread TrayApp.cs
Comment on lines +647 to +669
if (dialog.ShowDialog() != DialogResult.OK)
{
return null;
}

var modifiers = ModifierKeys.None;
if (ctrlCheckBox.Checked) modifiers |= ModifierKeys.Control;
if (altCheckBox.Checked) modifiers |= ModifierKeys.Alt;
if (shiftCheckBox.Checked) modifiers |= ModifierKeys.Shift;
if (winCheckBox.Checked) modifiers |= ModifierKeys.Windows;

if (modifiers == ModifierKeys.None)
{
return null;
}

if (keyCombo.SelectedIndex < 0)
{
return null;
}

var selectedKey = commonKeys[keyCombo.SelectedIndex];
return (modifiers, selectedKey);
Comment thread Config.cs
Comment on lines +42 to +43
// into non-nullable string properties, which would cause NullReferenceException
// downstream when HotkeyManager.TryParse calls Split().
Comment thread HotkeyManager.cs
@@ -0,0 +1,190 @@
using System.Diagnostics;
Comment thread TrayApp.cs
{
_config.HotkeyModifiers = previousModifiers;
_config.HotkeyKey = previousKey;
ShowError($"Could not register hotkey: {hotkeyError}");
Comment thread TrayApp.cs
Comment on lines +127 to +128
RegisterConfiguredHotkey();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Keyboard shortcut (hotkey) to toggle

2 participants