From 2c4cce0347d7bc41efbefba90376f2e53bc72183 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Fri, 29 Aug 2025 23:44:39 +0200 Subject: [PATCH] feat(hotkeys): add hotkey configuration for toggling tracking and single process --- .../Implementation/ThumbnailConfiguration.cs | 7 ++ .../Interface/IThumbnailConfiguration.cs | 1 + .../Services/ReRegisterHotkeysHandler.cs | 20 ++++ .../Messages/Services/ReRegisterHotkeys.cs | 5 + .../Implementation/MainFormPresenter.cs | 11 +++ .../Implementation/ThumbnailManager.cs | 93 +++++++++++++++++-- .../Services/Interface/IThumbnailManager.cs | 1 + .../View/Implementation/MainForm.Designer.cs | 79 +++++++++++++++- .../View/Implementation/MainForm.cs | 15 +++ .../View/Interface/IMainFormView.cs | 4 + 10 files changed, 228 insertions(+), 8 deletions(-) create mode 100644 src/Eve-O-Preview/Mediator/Handlers/Services/ReRegisterHotkeysHandler.cs create mode 100644 src/Eve-O-Preview/Mediator/Messages/Services/ReRegisterHotkeys.cs diff --git a/src/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs b/src/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs index c52a8d1..bfb4032 100644 --- a/src/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs +++ b/src/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs @@ -124,6 +124,8 @@ namespace EveOPreview.Configuration.Implementation { this.IconName = ""; this.LoginThumbnailLocation = new Point(5, 5); + this.ToggleTrackingHotkey = "Alt+F16"; + this.ToggleSingleProcessHotkey = "Control+F16"; this.ToggleAllThumbnailsHotkey = "Alt+F12"; this.ThumbnailsManuallyHidden = false; } @@ -320,6 +322,11 @@ namespace EveOPreview.Configuration.Implementation { get; set; } + [JsonProperty("ToggleSingleProcessHotkey")] + public string ToggleSingleProcessHotkey { + get; set; + } + [JsonProperty("ToggleAllThumbnailsHotkey")] public string ToggleAllThumbnailsHotkey { get; set; diff --git a/src/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs b/src/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs index 8c378ae..835d0ee 100644 --- a/src/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs +++ b/src/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs @@ -25,6 +25,7 @@ namespace EveOPreview.Configuration { Dictionary CycleGroup5ClientsOrder { get; set; } string ToggleTrackingHotkey { get; set; } + string ToggleSingleProcessHotkey { get; set; } string ToggleAllThumbnailsHotkey { get; set; } bool ThumbnailsManuallyHidden { get; set; } diff --git a/src/Eve-O-Preview/Mediator/Handlers/Services/ReRegisterHotkeysHandler.cs b/src/Eve-O-Preview/Mediator/Handlers/Services/ReRegisterHotkeysHandler.cs new file mode 100644 index 0000000..2e3b9f9 --- /dev/null +++ b/src/Eve-O-Preview/Mediator/Handlers/Services/ReRegisterHotkeysHandler.cs @@ -0,0 +1,20 @@ +using System.Threading; +using System.Threading.Tasks; +using EveOPreview.Mediator.Messages; +using EveOPreview.Services; +using MediatR; + +namespace EveOPreview.Mediator.Handlers.Services { + public sealed class ReRegisterHotkeysHandler : INotificationHandler { + private readonly IThumbnailManager _thumbnailManager; + + public ReRegisterHotkeysHandler(IThumbnailManager thumbnailManager) { + this._thumbnailManager = thumbnailManager; + } + + public Task Handle(ReRegisterHotkeys notification, CancellationToken cancellationToken) { + this._thumbnailManager.ReRegisterHotkeys(); + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/Eve-O-Preview/Mediator/Messages/Services/ReRegisterHotkeys.cs b/src/Eve-O-Preview/Mediator/Messages/Services/ReRegisterHotkeys.cs new file mode 100644 index 0000000..5a386f4 --- /dev/null +++ b/src/Eve-O-Preview/Mediator/Messages/Services/ReRegisterHotkeys.cs @@ -0,0 +1,5 @@ +using MediatR; + +namespace EveOPreview.Mediator.Messages { + public sealed class ReRegisterHotkeys : INotification {} +} \ No newline at end of file diff --git a/src/Eve-O-Preview/Presenters/Implementation/MainFormPresenter.cs b/src/Eve-O-Preview/Presenters/Implementation/MainFormPresenter.cs index 6b8d309..4c03f22 100644 --- a/src/Eve-O-Preview/Presenters/Implementation/MainFormPresenter.cs +++ b/src/Eve-O-Preview/Presenters/Implementation/MainFormPresenter.cs @@ -133,6 +133,10 @@ namespace EveOPreview.Presenters { this.View.AvailableProfiles = this._configuration.AvailableProfiles; this.View.CurrentProfile = this._configuration.CurrentProfile; + this.View.ToggleTrackingHotkey = this._configuration.ToggleTrackingHotkey; + this.View.ToggleSingleProcessHotkey = this._configuration.ToggleSingleProcessHotkey; + this.View.ToggleAllThumbnailsHotkey = this._configuration.ToggleAllThumbnailsHotkey; + this.View.IconName = this._configuration.IconName; } @@ -181,6 +185,13 @@ namespace EveOPreview.Presenters { this._configuration.AvailableProfiles = this.View.AvailableProfiles; this._configuration.CurrentProfile = this.View.CurrentProfile; + this._configuration.ToggleTrackingHotkey = this.View.ToggleTrackingHotkey; + this._configuration.ToggleSingleProcessHotkey = this.View.ToggleSingleProcessHotkey; + this._configuration.ToggleAllThumbnailsHotkey = this.View.ToggleAllThumbnailsHotkey; + + // Re-register hotkeys if they changed + await this._mediator.Send(new ReRegisterHotkeys()); + // Publish region settings update if they changed if (this._configuration.EnableThumbnailRegionSnipping != this.View.EnableThumbnailRegionSnipping || this._configuration.DefaultThumbnailRegion != this.View.DefaultThumbnailRegion) { diff --git a/src/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs b/src/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs index 4df6c3a..595e26a 100644 --- a/src/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs +++ b/src/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs @@ -52,6 +52,7 @@ namespace EveOPreview.Services { private List _cycleClientHotkeyHandlers = new List(); private HotkeyHandler _toggleTrackingHotkey; + private HotkeyHandler _toggleSingleProcessHotkey; private HotkeyHandler _toggleAllThumbnailsHotkey; #endregion @@ -107,10 +108,11 @@ namespace EveOPreview.Services { // RegisterCycleClientHotkey(this._configuration.CycleGroup5BackwardHotkeys?.Select(x => // this._configuration.StringToKey(x)), false, this._configuration.CycleGroup5ClientsOrder); // - // Setup toggle tracking hotkey (Ctrl+T) + // Setup toggle tracking hotkey var mainHandle = this._processMonitor.GetMainProcess().Handle; System.Diagnostics.Debug.WriteLine($"Registering hotkey with main window handle: {mainHandle}"); - this._toggleTrackingHotkey = new HotkeyHandler(mainHandle, Keys.Alt | Keys.F16); + var toggleTrackingKey = this._configuration.StringToKey(this._configuration.ToggleTrackingHotkey); + this._toggleTrackingHotkey = new HotkeyHandler(mainHandle, toggleTrackingKey); this._toggleTrackingHotkey.Pressed += (object s, HandledEventArgs e) => { var foregroundHandle = this._windowManager.GetForegroundWindowHandle(); if (foregroundHandle != IntPtr.Zero) { @@ -138,9 +140,10 @@ namespace EveOPreview.Services { var registered = this._toggleTrackingHotkey.Register(); System.Diagnostics.Debug.WriteLine($"Hotkey registration result: {registered}"); - // Setup single process tracking hotkey (Ctrl+F16) - var toggleSingleProcessHotkey = new HotkeyHandler(mainHandle, Keys.Control | Keys.F16); - toggleSingleProcessHotkey.Pressed += (object s, HandledEventArgs e) => { + // Setup single process tracking hotkey + var toggleSingleProcessKey = this._configuration.StringToKey(this._configuration.ToggleSingleProcessHotkey); + this._toggleSingleProcessHotkey = new HotkeyHandler(mainHandle, toggleSingleProcessKey); + this._toggleSingleProcessHotkey.Pressed += (object s, HandledEventArgs e) => { var foregroundHandle = this._windowManager.GetForegroundWindowHandle(); if (foregroundHandle != IntPtr.Zero) { uint processId; @@ -166,7 +169,7 @@ namespace EveOPreview.Services { } } }; - registered = toggleSingleProcessHotkey.Register(); + registered = this._toggleSingleProcessHotkey.Register(); System.Diagnostics.Debug.WriteLine($"Single process hotkey registration result: {registered}"); // Setup toggle all thumbnails hotkey @@ -182,6 +185,84 @@ namespace EveOPreview.Services { System.Diagnostics.Debug.WriteLine($"Toggle all thumbnails hotkey registration result: {registered}"); } + public void ReRegisterHotkeys() { + // Unregister existing hotkeys + this._toggleTrackingHotkey?.Unregister(); + this._toggleSingleProcessHotkey?.Unregister(); + this._toggleAllThumbnailsHotkey?.Unregister(); + + // Re-register with new settings + var mainHandle = this._processMonitor.GetMainProcess().Handle; + + var toggleTrackingKey = this._configuration.StringToKey(this._configuration.ToggleTrackingHotkey); + this._toggleTrackingHotkey = new HotkeyHandler(mainHandle, toggleTrackingKey); + this._toggleTrackingHotkey.Pressed += (object s, HandledEventArgs e) => { + var foregroundHandle = this._windowManager.GetForegroundWindowHandle(); + if (foregroundHandle != IntPtr.Zero) { + uint processId; + GetWindowThreadProcessId(foregroundHandle, out processId); + var process = Process.GetProcessById((int)processId); + + if (process != null) { + System.Diagnostics.Debug.WriteLine($"Found process: {process.ProcessName}"); + if (_configuration.IsExecutableToPreview(process.ProcessName)) { + System.Diagnostics.Debug.WriteLine("Removing from executables to preview"); + var exesToPreview = _configuration.ExecutablesToPreview.ToList(); + exesToPreview.Remove(process.ProcessName.ToLower()); + _configuration.ExecutablesToPreview = exesToPreview; + } else { + System.Diagnostics.Debug.WriteLine("Adding to executables to preview"); + var exesToPreview = _configuration.ExecutablesToPreview.ToList(); + exesToPreview.Add(process.ProcessName.ToLower()); + _configuration.ExecutablesToPreview = exesToPreview; + } + e.Handled = true; + } + } + }; + this._toggleTrackingHotkey.Register(); + + var toggleSingleProcessKey = this._configuration.StringToKey(this._configuration.ToggleSingleProcessHotkey); + this._toggleSingleProcessHotkey = new HotkeyHandler(mainHandle, toggleSingleProcessKey); + this._toggleSingleProcessHotkey.Pressed += (object s, HandledEventArgs e) => { + var foregroundHandle = this._windowManager.GetForegroundWindowHandle(); + if (foregroundHandle != IntPtr.Zero) { + uint processId; + GetWindowThreadProcessId(foregroundHandle, out processId); + var process = Process.GetProcessById((int)processId); + + if (process != null) { + System.Diagnostics.Debug.WriteLine($"Found process: {process.ProcessName} (PID: {process.Id})"); + + // Get the current tracked PID from ProcessMonitor + var currentTrackedPid = this._processMonitor.GetTrackedPid(); + + if (currentTrackedPid == process.Id) { + // Stop tracking this process + this._processMonitor.SetTrackedPid(0); + System.Diagnostics.Debug.WriteLine($"Stopped tracking process {process.Id}"); + } else { + // Start tracking this process + this._processMonitor.SetTrackedPid(process.Id); + System.Diagnostics.Debug.WriteLine($"Started tracking process {process.Id}"); + } + e.Handled = true; + } + } + }; + this._toggleSingleProcessHotkey.Register(); + + var toggleAllThumbnailsKey = this._configuration.StringToKey(this._configuration.ToggleAllThumbnailsHotkey); + this._toggleAllThumbnailsHotkey = new HotkeyHandler(mainHandle, toggleAllThumbnailsKey); + this._toggleAllThumbnailsHotkey.Pressed += (object s, HandledEventArgs e) => { + this._configuration.ThumbnailsManuallyHidden = !this._configuration.ThumbnailsManuallyHidden; + System.Diagnostics.Debug.WriteLine( + $"Toggled all thumbnails: {(this._configuration.ThumbnailsManuallyHidden ? "Hidden" : "Visible")}"); + e.Handled = true; + }; + this._toggleAllThumbnailsHotkey.Register(); + } + public IThumbnailView GetClientByTitle(string title) { return _thumbnailViews.FirstOrDefault(x => x.Value.Title == title).Value; } diff --git a/src/Eve-O-Preview/Services/Interface/IThumbnailManager.cs b/src/Eve-O-Preview/Services/Interface/IThumbnailManager.cs index 9551cdc..6f89d91 100644 --- a/src/Eve-O-Preview/Services/Interface/IThumbnailManager.cs +++ b/src/Eve-O-Preview/Services/Interface/IThumbnailManager.cs @@ -8,6 +8,7 @@ namespace EveOPreview.Services { void UpdateThumbnailsSize(); void UpdateThumbnailFrames(); void UpdateThumbnailRegionSettings(); + void ReRegisterHotkeys(); IThumbnailView GetClientByTitle(string title); IThumbnailView GetClientByPointer(System.IntPtr ptr); diff --git a/src/Eve-O-Preview/View/Implementation/MainForm.Designer.cs b/src/Eve-O-Preview/View/Implementation/MainForm.Designer.cs index 4677ef2..f825221 100644 --- a/src/Eve-O-Preview/View/Implementation/MainForm.Designer.cs +++ b/src/Eve-O-Preview/View/Implementation/MainForm.Designer.cs @@ -64,6 +64,12 @@ namespace EveOPreview.View { HideThumbnailsOnLostFocusCheckBox = new CheckBox(); EnablePerClientThumbnailsLayoutsCheckBox = new CheckBox(); MinimizeToTrayCheckBox = new CheckBox(); + ToggleTrackingHotkeyLabel = new Label(); + ToggleTrackingHotkeyTextBox = new TextBox(); + ToggleSingleProcessHotkeyLabel = new Label(); + ToggleSingleProcessHotkeyTextBox = new TextBox(); + ToggleAllThumbnailsHotkeyLabel = new Label(); + ToggleAllThumbnailsHotkeyTextBox = new TextBox(); EnableThumbnailRegionSnippingCheckBox = new CheckBox(); RegionLeftLabel = new Label(); RegionLeftNumericEdit = new NumericUpDown(); @@ -256,6 +262,12 @@ namespace EveOPreview.View { GeneralSettingsPanel.Controls.Add(HideThumbnailsOnLostFocusCheckBox); GeneralSettingsPanel.Controls.Add(EnablePerClientThumbnailsLayoutsCheckBox); GeneralSettingsPanel.Controls.Add(MinimizeToTrayCheckBox); + GeneralSettingsPanel.Controls.Add(ToggleTrackingHotkeyLabel); + GeneralSettingsPanel.Controls.Add(ToggleTrackingHotkeyTextBox); + GeneralSettingsPanel.Controls.Add(ToggleSingleProcessHotkeyLabel); + GeneralSettingsPanel.Controls.Add(ToggleSingleProcessHotkeyTextBox); + GeneralSettingsPanel.Controls.Add(ToggleAllThumbnailsHotkeyLabel); + GeneralSettingsPanel.Controls.Add(ToggleAllThumbnailsHotkeyTextBox); GeneralSettingsPanel.Dock = DockStyle.Fill; GeneralSettingsPanel.Location = new Point(4, 4); GeneralSettingsPanel.Margin = new Padding(4); @@ -378,6 +390,63 @@ namespace EveOPreview.View { MinimizeToTrayCheckBox.UseVisualStyleBackColor = true; MinimizeToTrayCheckBox.CheckedChanged += OptionChanged_Handler; // + // ToggleTrackingHotkeyLabel + // + ToggleTrackingHotkeyLabel.AutoSize = true; + ToggleTrackingHotkeyLabel.Location = new Point(9, 230); + ToggleTrackingHotkeyLabel.Margin = new Padding(4, 0, 4, 0); + ToggleTrackingHotkeyLabel.Name = "ToggleTrackingHotkeyLabel"; + ToggleTrackingHotkeyLabel.Size = new Size(94, 15); + ToggleTrackingHotkeyLabel.TabIndex = 28; + ToggleTrackingHotkeyLabel.Text = "Toggle Tracking:"; + // + // ToggleTrackingHotkeyTextBox + // + ToggleTrackingHotkeyTextBox.Location = new Point(145, 227); + ToggleTrackingHotkeyTextBox.Margin = new Padding(4); + ToggleTrackingHotkeyTextBox.Name = "ToggleTrackingHotkeyTextBox"; + ToggleTrackingHotkeyTextBox.Size = new Size(137, 23); + ToggleTrackingHotkeyTextBox.TabIndex = 29; + ToggleTrackingHotkeyTextBox.TextChanged += OptionChanged_Handler; + // + // ToggleSingleProcessHotkeyLabel + // + ToggleSingleProcessHotkeyLabel.AutoSize = true; + ToggleSingleProcessHotkeyLabel.Location = new Point(9, 260); + ToggleSingleProcessHotkeyLabel.Margin = new Padding(4, 0, 4, 0); + ToggleSingleProcessHotkeyLabel.Name = "ToggleSingleProcessHotkeyLabel"; + ToggleSingleProcessHotkeyLabel.Size = new Size(124, 15); + ToggleSingleProcessHotkeyLabel.TabIndex = 30; + ToggleSingleProcessHotkeyLabel.Text = "Toggle Single Process:"; + // + // ToggleSingleProcessHotkeyTextBox + // + ToggleSingleProcessHotkeyTextBox.Location = new Point(145, 257); + ToggleSingleProcessHotkeyTextBox.Margin = new Padding(4); + ToggleSingleProcessHotkeyTextBox.Name = "ToggleSingleProcessHotkeyTextBox"; + ToggleSingleProcessHotkeyTextBox.Size = new Size(137, 23); + ToggleSingleProcessHotkeyTextBox.TabIndex = 31; + ToggleSingleProcessHotkeyTextBox.TextChanged += OptionChanged_Handler; + // + // ToggleAllThumbnailsHotkeyLabel + // + ToggleAllThumbnailsHotkeyLabel.AutoSize = true; + ToggleAllThumbnailsHotkeyLabel.Location = new Point(9, 290); + ToggleAllThumbnailsHotkeyLabel.Margin = new Padding(4, 0, 4, 0); + ToggleAllThumbnailsHotkeyLabel.Name = "ToggleAllThumbnailsHotkeyLabel"; + ToggleAllThumbnailsHotkeyLabel.Size = new Size(129, 15); + ToggleAllThumbnailsHotkeyLabel.TabIndex = 32; + ToggleAllThumbnailsHotkeyLabel.Text = "Toggle All Thumbnails:"; + // + // ToggleAllThumbnailsHotkeyTextBox + // + ToggleAllThumbnailsHotkeyTextBox.Location = new Point(145, 287); + ToggleAllThumbnailsHotkeyTextBox.Margin = new Padding(4); + ToggleAllThumbnailsHotkeyTextBox.Name = "ToggleAllThumbnailsHotkeyTextBox"; + ToggleAllThumbnailsHotkeyTextBox.Size = new Size(137, 23); + ToggleAllThumbnailsHotkeyTextBox.TabIndex = 33; + ToggleAllThumbnailsHotkeyTextBox.TextChanged += OptionChanged_Handler; + // // ThumbnailTabPage // ThumbnailTabPage.BackColor = SystemColors.Control; @@ -1354,7 +1423,7 @@ namespace EveOPreview.View { // VersionLabel // VersionLabel.AutoSize = true; - VersionLabel.Font = new Font("Microsoft Sans Serif", 12F, FontStyle.Bold); + VersionLabel.Font = new Font("Microsoft Sans Serif", 12F, FontStyle.Bold, GraphicsUnit.Point); VersionLabel.Location = new Point(155, 10); VersionLabel.Margin = new Padding(4, 0, 4, 0); VersionLabel.Name = "VersionLabel"; @@ -1365,7 +1434,7 @@ namespace EveOPreview.View { // NameLabel // NameLabel.AutoSize = true; - NameLabel.Font = new Font("Microsoft Sans Serif", 12F, FontStyle.Bold); + NameLabel.Font = new Font("Microsoft Sans Serif", 12F, FontStyle.Bold, GraphicsUnit.Point); NameLabel.Location = new Point(5, 10); NameLabel.Margin = new Padding(4, 0, 4, 0); NameLabel.Name = "NameLabel"; @@ -1530,5 +1599,11 @@ namespace EveOPreview.View { private RadioButton OverlayLabelSWRadioButton; private Label label1; private ComboBox AnimationStyleCombo; + private Label ToggleTrackingHotkeyLabel; + private TextBox ToggleTrackingHotkeyTextBox; + private Label ToggleSingleProcessHotkeyLabel; + private TextBox ToggleSingleProcessHotkeyTextBox; + private Label ToggleAllThumbnailsHotkeyLabel; + private TextBox ToggleAllThumbnailsHotkeyTextBox; } } \ No newline at end of file diff --git a/src/Eve-O-Preview/View/Implementation/MainForm.cs b/src/Eve-O-Preview/View/Implementation/MainForm.cs index afd483e..8c9cfa7 100644 --- a/src/Eve-O-Preview/View/Implementation/MainForm.cs +++ b/src/Eve-O-Preview/View/Implementation/MainForm.cs @@ -229,6 +229,21 @@ namespace EveOPreview.View { set => ThumbnailSnapRangeNumericEdit.Value = value; } + public string ToggleTrackingHotkey { + get => this.ToggleTrackingHotkeyTextBox.Text; + set => this.ToggleTrackingHotkeyTextBox.Text = value; + } + + public string ToggleSingleProcessHotkey { + get => this.ToggleSingleProcessHotkeyTextBox.Text; + set => this.ToggleSingleProcessHotkeyTextBox.Text = value; + } + + public string ToggleAllThumbnailsHotkey { + get => this.ToggleAllThumbnailsHotkeyTextBox.Text; + set => this.ToggleAllThumbnailsHotkeyTextBox.Text = value; + } + public bool EnableActiveClientHighlight { get => this.EnableActiveClientHighlightCheckBox.Checked; set => this.EnableActiveClientHighlightCheckBox.Checked = value; diff --git a/src/Eve-O-Preview/View/Interface/IMainFormView.cs b/src/Eve-O-Preview/View/Interface/IMainFormView.cs index 983e93a..5f3366c 100644 --- a/src/Eve-O-Preview/View/Interface/IMainFormView.cs +++ b/src/Eve-O-Preview/View/Interface/IMainFormView.cs @@ -47,6 +47,10 @@ namespace EveOPreview.View { string CurrentProfile { get; set; } List AvailableProfiles { get; set; } + string ToggleTrackingHotkey { get; set; } + string ToggleSingleProcessHotkey { get; set; } + string ToggleAllThumbnailsHotkey { get; set; } + string IconName { get; set; } void SetDocumentationUrl(string url);